- Don't Fear the Reaper
- Life in the fast lane
- Go Your Own Way. Part one. Stack
- Go Your Own Way. Part two. A bunch
D, like many languages ββin use today, comes with a Garbage Collector (GC). Many types of software can be developed without thinking about GC at all, taking full advantage of its advantages. However, the GC has its flaws, and in some scenarios garbage collection is undesirable. For such cases, the language allows you to temporarily disable the garbage collector, or even do without it altogether.
To get the most out of the garbage collector and minimize its drawbacks, you need to have a good understanding of how GC works in D language. A good place to start is the Garbage Collection page on dlang.org , which provides a rationale for GC in D and provides a few tips on how to work with him. This is the first in a series of articles to cover the topic in more detail.
This time we will touch only on the very basics, focusing on the functions of the language that can cause memory allocation through the GC. Future articles will present ways to disable GC if necessary, as well as idioms to help deal with its non-determinism (for example, resource management in object destructors controlled by GC).
The very first thing to understand is that D's garbage collector is only triggered during memory allocation and only if there is no memory to allocate. He does not sit in the background, periodically scanning the pile and collecting trash. You need to understand this in order to write GC-controlled memory efficient code. Consider the following example:
void main() {
int[] ints;
foreach(i; 0..100) {
ints ~= i;
}
}
This program creates a dynamic array of type values int
, and then uses the join operator in D to add numbers from 0 to 99 to it foreach
. What is not obvious to the untrained eye is that the join operator allocates memory for added values ββthrough the 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 (, , , β - ).
Now that we've got a grasp of the basics of working with GC, in the next article in this series we'll see what tools in the language and compiler will allow us to disable the garbage collector and ensure that critical areas of the program don't access the GC.
Thanks to Guillaume Piolat and Steve Schweihoffer for their help in preparing this article.