cross-post from core:
After examining how the 1.8.6 gc works, I had a few thoughts:
Background:
It seems that on a ‘cpu intensive’ program (one that generates a lot of
discardable objects–quite common), there is a competition between two
aspects of the gc to call garbage_collect first. They are:
-
If you run out of available heap slots ruby calls garbage_collect,
and
if
“FREE_MIN” slots now exist (by default 4096) then it returns and leaves
the heap the same size. It also resets the current ‘malloc’ed bytes’
counter to 0, since it called garbage_collect.
-
If you reach GC_MALLOC_LIMIT of malloc’ed bytes, then it calls
garbage_collect, resets it to 0.
Anyway so what happens in today’s implementations is that number 1 is
called often (I believe) preventing number 2 from ever even springing,
as it
resets the current count of malloc’ed bytes. It’s like garbage_collect
is
trying to serve 2 masters, and ends up serving just the one. I see this
as curious as it basically disallows GC_MALLOC_LIMIT from being reached,
which is not what you would expect.
Thoughts?
On another point, I have a question on this line of code, run at the end
of garbage collection:
if (malloc_increase > malloc_limit) {
malloc_limit += (malloc_increase - malloc_limit) * (double)live /
(live + freed); // this line
if (malloc_limit < GC_MALLOC_LIMIT) malloc_limit = GC_MALLOC_LIMIT;
}
I haven’t checked this, but it seems to me that It seems to me that
(malloc_increase - malloc_limit) will always be a very small number (?)
which may not be what was expected. I could be wrong.
So my question is "what should the GC do, and when?
Any thoughts?
In my opinion, if it runs out of heap slots available, it should call
garbage_collect AND increase the heap size (so that next time it won’t
run out, and will have enough to hopefully reach GC_MALLOC_LIMIT).
I think when it does reach GC_MALLOC_LIMIT malloc’ed bytes, it should
set it
new_malloc_limit = GC_MALLOC_LIMIT *
(1 - percent_of_recent_allocated_memory_that_was_freed)
to allow the malloc_limit to change dynamically, maybe with a fixed max
size.
So my question is what should best happen?
Ruby rox.