GC.collect inflating memory usage?
cc
cc at nevernet.com
Sat Dec 7 11:20:17 UTC 2019
Given the following program:
//version=FREE;
//version=COLLECT;
import std.stdio;
import std.datetime.stopwatch;
import core.memory;
immutable int[] intZ =
[1,2,3,4,4,6,6,8,8,65,8,23,76,2,57,264,23,4,4,6,6,8,8,65,8,23,76,2,57,264,23,4,4,6,6,8,8,65,8,23,76,2,57,264,23,4,4,6,6,8,8,65,8,23,76,2,57,264,23,4,4,6,6,8,8,65,8,23,76,2,57,264,23,4,4,6,6,8,8,65,8,23,76,2,57,264,23,4,4,6,6,8,8,65,8,23,76,2,57,264,23,4,4,6,6,8,8,65,8,23,76,2,57,264,23,4,4,6,6,8,8,65,8,23,76,2,57,264,23];
void main() {
writeln(GC.stats);
enum max = 100000;
StopWatch sw;
sw.start();
foreach (i; 0 .. max) {
bool doprint = !(i % (max/10));
int[] z = intZ.dup;
if (doprint) writef("%7d ", GC.stats.usedSize);
version(FREE) GC.free(cast(void*) z.ptr);
version(COLLECT) GC.collect();
if (doprint) writefln("%7d", GC.stats.usedSize);
}
sw.stop();
writefln("Elapsed: %d ms", sw.peek.total!"msecs");
}
When compiled with neither the FREE or COLLECT versions, I get
results like this typically:
Stats(16, 1048560, 16)
848 848
883104 883104
711072 711072
539040 539040
367008 367008
191696 191696
19664 19664
887200 887200
715168 715168
540672 540672
Elapsed: 11 ms
When only the FREE line is enabled, I see results like this:
// FREE
Stats(16, 1048560, 16)
848 32
848 32
848 32
848 32
848 32
848 32
848 32
848 32
848 32
848 32
Elapsed: 12 ms
When only the COLLECT line is enabled, I see results like this:
// COLLECT
Stats(16, 1048560, 16)
848 4096
4928 4096
4928 4096
4928 4096
9024 8192
4928 4096
4928 4096
4928 4096
4928 4096
4928 4096
Elapsed: 1130 ms
But when both FREE and COLLECT are enabled, things seem to spiral
out of control:
// FREE, COLLECT
Stats(16, 1048560, 16)
848 4096
40960832 40964096
81920832 81924096
122880832 122884096
163840832 163844096
204800832 204804096
245760832 245764096
286720832 286724096
327680832 327684096
368640832 368644096
Elapsed: 29143 ms
I wouldn't normally call GC.collect on every frame in my
application, but I'm curious why this is happening and if there
is unnecessary bloat being added somehow when I do choose to call
GC.free manually and garbage collection later occurs in a
long-running program. Ideally I'd like to free up as many
objects and arrays as soon as they become unused to avoid lengthy
collections reducing performance. I know that
std.container.array is one alternative to using D's GC-managed
dynamic arrays, but could I run into the same issue when trying
to manually deallocate class objects as well?
Using DMD32 D Compiler v2.089.0-dirty
More information about the Digitalmars-d-learn
mailing list