- Ne craignez pas le faucheur
- La vie à vitesse grand V
- Suis ton propre chemin. Partie un. Empiler
- Suis ton propre chemin. Deuxième partie. Tas
D, comme de nombreux langages largement utilisés aujourd'hui, est livré avec un Garbage Collector (GC). De nombreux types de logiciels peuvent être développés sans penser du tout à GC, profitant pleinement de ses avantages. Cependant, GC a ses défauts et le garbage collection n'est pas souhaitable dans certains scénarios. Dans de tels cas, le langage vous permet de désactiver temporairement le ramasse-miettes, voire de vous en passer complètement.
Pour tirer le meilleur parti du ramasse-miettes et minimiser ses inconvénients, vous devez comprendre comment le GC fonctionne en langage D. Un bon point de départ est la page Garbage Collection sur dlang.org , qui apporte la justification du GC en langage D et en donne quelques des conseils sur la façon de travailler avec lui. Ceci est le premier d'une série d'articles qui vise à couvrir le sujet plus en détail.
Cette fois, nous ne toucherons qu'aux principes de base, en nous concentrant sur les fonctions du langage qui peuvent provoquer l'allocation de mémoire via le GC. Les prochains articles présenteront des moyens de désactiver GC en cas de besoin, ainsi que des idiomes pour aider à faire face à son non-déterminisme (par exemple, la gestion des ressources dans les destructeurs d'objets sous contrôle GC).
La toute première chose à comprendre est que le ramasse-miettes de D n'est déclenché que pendant l'allocation de mémoire et uniquement s'il n'y a pas de mémoire à allouer. Il ne s'assied pas à l'arrière-plan, balayant périodiquement la pile et ramassant les ordures. Cela doit être compris afin d'écrire du code qui utilise efficacement la mémoire sous le contrôle du GC. Prenons l'exemple suivant:
void main() {
int[] ints;
foreach(i; 0..100) {
ints ~= i;
}
}
Ce programme crée un tableau dynamique de valeurs de type int
, puis utilise l'opérateur de jointure en D pour y ajouter des nombres de 0 à 99 foreach
. Ce qui n'est pas évident pour un œil inexpérimenté, c'est que l'opérateur de jointure alloue de la mémoire pour les valeurs ajoutées via le garbage collector.
D . , . , , . , , capacity
. , , .
void main() {
import std.stdio : writefln;
int[] ints;
size_t before, after;
foreach(i; 0..100) {
before = ints.capacity;
ints ~= i;
after = ints.capacity;
if(before != after) {
writefln("Before: %s After: %s",
before, after);
}
}
}
DMD 2.073.2, — GC. , GC . . , GC, .
, before
after
. : 0, 3, 7, 15, 31, 63, 127. ints
100 , 27 , , 255, . , , D, . , GC , (Steve Schveighoffer) .
, , GC . , , «» . GC .
, C C++, , . , — , . , GC D , . :
void main() {
int[] ints = new int[](100);
foreach(i; 0..100) {
ints[i] = i;
}
}
. , — . 100 . new
100, .
: reserve
:
void main() {
int[] ints;
ints.reserve(100);
foreach(i; 0..100) {
ints ~= i;
}
}
100 , ( length
0), . , 100 , , .
new
reserve
, , GC.malloc
.
import core.memory;
void* intsPtr = GC.malloc(int.sizeof * 100);
auto ints = (cast(int*)intsPtr)[0 .. 100];
auto ints = [0, 1, 2];
, enum
.
enum intsLiteral = [0, 1, 2];
auto ints1 = intsLiteral;
auto ints2 = intsLiteral;
enum
. — . , . ints1
, ints2
, :
auto ints1 = [0, 1, 2];
auto ints2 = [0, 1, 2];
int[3] noAlloc1 = [0, 1, 2];
auto noAlloc2 = "No Allocation!";
:
auto a1 = [0, 1, 2];
auto a2 = [3, 4, 5];
auto a3 = a1 ~ a2;
D , , . : keys
values
, . , , - , — . , GC.
- , , , . , . , . D : byKey
, byValue
byKeyValue
. , . , , . Ranges More Range (Ali Çehreli) Programming in D.
— , — . , Garbage Collection — assert
. , assert
, AssertError
, D, ( , GC).
, Phobos — D. - - Phobos’ GC, , . , Phobos GC. , , , , , . GC (, , , — - ).
Maintenant que nous avons une compréhension des bases du travail avec GC, dans le prochain article de cette série, nous verrons quels outils dans le langage et le compilateur nous permettront de désactiver le ramasse-miettes et de garantir que les zones critiques du programme n'accèdent pas au GC.
Merci à Guillaume Piolat et Steve Schweihoffer pour leur aide dans la préparation de cet article.