[Mono-list] Garbage collection and memory usage

Georgi Moskov g.moskov at gmail.com
Wed Apr 19 04:20:33 EDT 2006


Hi Miguel,

Thanks for the answer.

> We looked at the problem, and it boils down to the fact that Mono does
> not have a compacting GC.

After making some tests and googling a lot, I came to the same
conclusion. But this only explains why the memory usage is so big, and
keeps growing, it doesn't explain why mono "hangs" and .aspx pages are
not processed when there is still free memory on the machine.

> This test is generating some very large datasets that then get their
> viewstate serialized, it is something that Microsoft explicitly states
> is a bad idea.

Ofcourse it is, but it helped to quickly reproduce the problem ;-)

About the memory fragmentation, we managed to narrow down a little the
memory usage by implemeting Dispose() here and there, but I still
can't quite understand how and why this works, so here is a testcase:

http://hosting.telecoms.bg/~moskov/memtest.cs

In the first case we do the following:

	while(true)
	{
		Console.WriteLine("new iteration");
		string s = new String('a', 20000000);
		s = null;
						
		//testString s = new testString();
		//s.Dispose();
	}

When I run the program with the desc-heap profiler, I see the following:

new iteration
Checkpoint at 2379 for gc
   System.String : 40002024
new iteration
Checkpoint at 2433 for gc
   System.String : 40002024
new iteration
Checkpoint at 2491 for gc
   System.String : 80002038
heap resized to 120594432 @ 2491
Checkpoint at 2491 for heap-resize
   System.String : 80002038
new iteration
heap resized to 160727040 @ 2601
Checkpoint at 2601 for heap-resize
   System.String : 120002052
new iteration
Checkpoint at 2697 for gc
   System.String : 40002024
new iteration
new iteration
new iteration
Checkpoint at 2884 for gc
   System.String : 40002024

   And from now on, the GC is called on every 4th iteration, and
allocated memory never drops below 160Mb and often reaches 240Mb and
sometimes more. I surpose that calling GC more rarely is some kind of
optimization, but it doesn't help a lot here, because we don't have
problems with the speed of execution, but with the memory usage.

   In the other scenario I use testString which implements IDisposable
and basicaly does the same thing. But in this case it takes some time
untill GC starts to be called on every 2nd itaration, and even more
time to start beeing called on every 4th, and allocated memory never
exceeds 160Mb.

  I tested in the same way one of our most frequently called and
obviously memory fragmenting classes. In the first case, when run in a
while(true) loop for 5 minutes, it allocated 39Mb of memory, and in
the second case when we implemented Dispose() it allocated 12Mb of
memory.

  I hope that I haven't gotten something totaly wrong and confused the
situation more ;-) Any feedback is highly apreciated.

Regards,
Georgi Moskov


More information about the Mono-list mailing list