[Gc] why USE_MUNMAP isn't the default for the collector? (repost)
glauco at virgilio
glauco.masotti at virgilio.it
Thu May 4 00:41:30 PDT 2006
Hello. I am reposting a text-only version of my previous message, as nothing of the former appeared.
you may remember me as I am cited, in the README.changes file, for a small contribution that I gave in 2003.
Although I have been following with attention the developments of your garbage collector software for many years,
I had few occasions to effectively use it, mainly because I had to work in the framework of very large applications
already developed with a malloc/free approach.
In the latest 3-4 years I could move more freely on applications developed newly from scratch.
On one of these I opted for manual memory management after experimenting with your collector for a while, because I
found manual management more efficient.
This application manages a lot of temporary small structures, but also maintains some large arrays of structures for
reuse in subsequent runs.
The GC version was a 10-20% slower. However I had recently reconsidered this and after some reorganization of the code
the result turned in favor of the GC.
In particular it has been decisive to split the structures stored in the large arrays, putting apart their pointer-free
in order to make use of GC_MALLOC_ATOMIC for the large arrays of them.
The version with the GC is actually from 10 to 30% faster, and is more successful in reclaiming memory and in keeping
heap size small,
so I decided, from now on, unless new facts changes this situation, to rely steadily on the GC.
However all the above is true if I use the GC with the USE_MUNMAP option enabled, otherwise the heap used is much larger
and it tends to grow almost monotonically.
I am thus wondering why USE_MUNMAP isn't the default for the collector? Moreover in version 6.6, it won't even compile
unless you also enable USE_MMAP (!?).
This at least is what happens under Windows (I am using the GC on Windows in a VC++ environment, linking the GC as a
In the previous version that I used (6.2) wasn't like this, so the first time I saw this I wonder if the USE_MUNMAP
option were still working or not.
You will find attached some snapshot of memory allocation that I made running my application in the same situation,
using version 6.2 and 6.6 with or without the USE_MUNMAP option enabled. These images shows clearly what happens,
it also seems that version 6.6 manages the heap a little better, it allocates less memory and heap size appears to grow
and shrink more regularly.
Is there any drawback in enabling this option? Is there something wrong in my application that I need to use this
option? Or is it a problem that arises in Windows only?
Having stated briefly the above as the main question of the present query, there are a number of aspects that I think
are worth to be examined in more detail.
I hope you will find them interesting and I will appreciate your related comment or advice.
First of all I have to explain how all this started.
The previous version of my application, with malloc/free, was checked for leaks using version 6.2 of the GC, and there
were none, but after some months and many changes
I noticed an increase in allocated memory after subsequent runs of the application. Obviously I suspected that some
change gave rise to a leak,
but despite my efforts and many investigations, with or without the help of the GC, I was unable to find such a leak.
The collector didn't find any leak, it was only giving those obscure messages of the type: "Leaked composite object at
start: 0x..., appr. length: ...".
By reviewing the posts I found that other users have reported this, but you didn't clarify why the collector reports
these messages which are apparently meaningless.
Also checking with repeated calls of GC_generate_random_backtrace, everything that was found in memory had reasons to be
there, thus I found no useless retained reference.
At this point I didn't know how to get rid of this behavior that at the beginning of each run was steeling about 10 MB,
increasing each time the heap size.
Luckily I found that linking with the GC the heap size remained stable! Thus either a misterious leak existed and the GC
is better in reclaiming memory than
the manual malloc/free management, or it is able to use memory more efficiently than the standard allocator... or else
Therefore I decided to use the collector if I could be able to improve speed at least at the same level of the manual
As it happens sometimes, not all what seems bad comes to harm, and at the end I now have a faster application which uses
However, as it was not simple to get here, and I made many trials, in addition to what I said above, may be that someone
is interested in what else I found out,
and maybe that you want to confirm if what follows makes sense and corresponds to your experience.
1) USE_MUNMAP introduces a penalty of about 1-2% in total execution time, but, as I said above, it is essential to keep
heap size small.
2) Contrarily to what I expected, using LARGE_CONFIG is faster.
3) Using the IGNORE_OFF_PAGE versions of malloc and malloc_atomic for large arrays keep the collector silent (otherwise
it warns with:
"Repeated allocation of very large block (appr. size ...): may lead to memory leak and poor performance"),
but it is a little bit slower than using normal GC_MALLOC or GC_MALLOC_ATOMIC and explicitly deallocate them with
this approach could perhaps be preferred if these large arrays are only a few, isn't it?
4) I build my application linking the GC in VC++ as a static library built using the multithreaded standard libraries,
as I found this solution
slightly faster than building with single threaded versions (even if I don't use threads).
5) Version 6.6 is slightly faster (1% or less in final timing) than 6.2 (not bad :-).
Thank you for your attention so far.
--- Glauco Masotti
More information about the Gc