Thread overview
GC behavior
Jun 07, 2019
Gregor Mückl
Jun 07, 2019
KnightMare
Jun 07, 2019
KnightMare
Jun 07, 2019
Gregor Mückl
Jun 07, 2019
KnightMare
Jun 08, 2019
Gregor Mückl
Jun 07, 2019
KnightMare
Jun 07, 2019
Gregor Mückl
June 07, 2019
Hi!

I'm not 100% sure if I'm in the right here, but I believe that the following program shouldn't have unbounded heap growth to the point where it runs out of memory:

module gctest;

import core.memory;
import core.thread;

void main()
{
    for(int i = 0; i < 10000; i++) {
        int[] x = new int[10000000];
        Thread.sleep(dur!"msecs"(200));
        //GC.collect(); // keeps program from failing
    }
}

If GC.collect() is called constantly, heap size stays pretty much constant. Tested only on Windows 10 (64 bit) with DMD 2.086.0 so far. I'd say that this behavior is a bug.

June 07, 2019
I also noticed:
where code with arrays allocations compiled by LDC work ok, code by DMD is failed.
"gc:precise" doesn't help (maybe false positives scans.. dunno).
this code by DMD crashes for me at -m32 only
June 07, 2019
Windows Server 2019 (x64)
DMD 2.086.0
LDC 1.16.0-beta2


June 07, 2019
and yes, LDC drops all code in main, coz u dont use arrays/results and alloc int[] do nothing too (no constructors with some logic)
so, I checked with sum(array) and printing result (=0)
June 07, 2019
On Friday, 7 June 2019 at 12:28:50 UTC, Gregor Mückl wrote:
> Hi!
>
> I'm not 100% sure if I'm in the right here, but I believe that the following program shouldn't have unbounded heap growth to the point where it runs out of memory:
>
> module gctest;
>
> import core.memory;
> import core.thread;
>
> void main()
> {
>     for(int i = 0; i < 10000; i++) {
>         int[] x = new int[10000000];
>         Thread.sleep(dur!"msecs"(200));
>         //GC.collect(); // keeps program from failing
>     }
> }
>
> If GC.collect() is called constantly, heap size stays pretty much constant. Tested only on Windows 10 (64 bit) with DMD 2.086.0 so far. I'd say that this behavior is a bug.

It's a bit stranger than that: the following program doesn't fail only because it has the writeln with the string concatenation in it. I discovered it by accident while trying to look into how Windows reports available memory to 32 bit programs.

module gctest;

import core.thread;
import std.conv;
import std.stdio;

void main()
{
    for(int i = 0; i < 10000; i++) {
        int[] x = new int[10000000];
        Thread.sleep(dur!"msecs"(200));
        writeln("allocation " ~ to!string(i));
    }
}

Just the writeln without any concatenation will still not trigger garbage collection runs. What is it about the ~ operator implementation that changes the behavior so drastically?

As a side note, I don't think that GlobalMemoryStatus on Windows works the way the GC code thinks it's working. It will always happily report 2^31 bytes total and available memory, no matter how big the heap of the 32 bit program is. So isLowOnMem in gc/os.d should actually be broken in this particular situation.
June 07, 2019
On Friday, 7 June 2019 at 14:24:23 UTC, KnightMare wrote:
> I also noticed:
> where code with arrays allocations compiled by LDC work ok, code by DMD is failed.
> "gc:precise" doesn't help (maybe false positives scans.. dunno).
> this code by DMD crashes for me at -m32 only

Thanks for reproducing! So it's a dmd bug then.

DMD automatically generates a 32 bit executable for me, so my tests are hitting the 4GB boundary long before physical memory availability becomes an issue.

GC.collect() does collect the arrays, so I don't think that false positives during the scan shouldn't be the issue.
June 07, 2019
I filled issue https://issues.dlang.org/show_bug.cgi?id=19947
add something if u want (maybe link to this topic)


June 08, 2019
On Friday, 7 June 2019 at 14:47:44 UTC, KnightMare wrote:
> I filled issue https://issues.dlang.org/show_bug.cgi?id=19947
> add something if u want (maybe link to this topic)

Thanks for reporting! I'll monitor the bug there.