Does garbage collector D work?

So, I tried to check if the garbage collector D is working properly by running this program on Windows.

DMD 2.057 and 2.058 beta give the same result, regardless of whether I -release , -inline , -O , etc.

Code:

 import core.memory, std.stdio; extern(Windows) int GlobalMemoryStatusEx(ref MEMORYSTATUSEX lpBuffer); struct MEMORYSTATUSEX { uint Length, MemoryLoad; ulong TotalPhys, AvailPhys, TotalPageFile, AvailPageFile; ulong TotalVirtual, AvailVirtual, AvailExtendedVirtual; } void testA(size_t count) { size_t[] a; foreach (i; 0 .. count) a ~= i; //delete a; } void main() { MEMORYSTATUSEX ms; ms.Length = ms.sizeof; foreach (i; 0 .. 32) { testA(16 << 20); GlobalMemoryStatusEx(ms); stderr.writefln("AvailPhys: %s MiB", ms.AvailPhys >>> 20); } } 

The output was:

 AvailPhys: 3711 MiB AvailPhys: 3365 MiB AvailPhys: 3061 MiB AvailPhys: 2747 MiB AvailPhys: 2458 MiB core.exception.OutOfMemoryError 

When I uncommented the delete a; The result was

 AvailPhys: 3714 MiB AvailPhys: 3702 MiB AvailPhys: 3701 MiB AvailPhys: 3702 MiB AvailPhys: 3702 MiB ... 

So, I think the question is obvious ... does the GC really work?

+4
source share
4 answers

It looks like a regression - it does not happen in D1 (DMD 1.069). Recently, David Simcha has been optimizing the GC, so he may have something to do with it. Please write a bug report.

+3
source

The problem here is the false pointers. D garbage collector is conservative, that is, it does not always know what a pointer is and what is not. Sometimes we have to assume that bit patterns that would point to GC-allocated memory, if interpreted as pointers, are pointers. This is a big problem for large distributions, since large blocks are a larger target for false pointers.

You allocate about 48 MB each time you call testA() . In my experience, this is enough to almost guarantee that there will be a 32-bit system in the block. You will probably get better results if you compile your code in 64-bit mode (supported on Linux, OSX and FreeBSD, but not on Windows), since 64-bit address space is much less common.

As for my GC optimizations (I'm David Simcha, which CyberShadow mentions), there were two lots. One of them was> 6 months old and did not cause any problems. The other is still considered a pull request and is not yet in the main druntime tree. This is probably not a problem.

In the short term, the solution is to manually free these huge blocks. In the long run, we need to add an accurate scan, at least for the heap. (Exactly scanning the stack is much more complicated.) I wrote a patch to do this a couple of years ago, but it was rejected because it relied on templates and evaluated a compile-time function to generate pointer offset information for each data type. We hope that this information will ultimately be generated directly by the compiler, and I will be able to re-create my exact patch to scan the garbage heap.

+8
source

PS If you recompile Druntime with DFLAGS set to -debug=PRINTF in the makefile, you will get information about when the GC allocates / frees the system through the console. :)

+2
source

He works. The current implementation simply does not free memory from the operating system. Although the GC reuses the acquired memory, so this is not a real leak.

+1
source

Source: https://habr.com/ru/post/1389970/


All Articles