I wrote a patch to Ruby 1.6.0pre2's gc.c that makes gc frequency inversely
proportional to the number of currently allocated objects, so that % of
time spent on GC remains about the same. With Aleksi's program (see
message #4407) I get the following results. My version of the GC uses
about 20% more RAM, but one can fumble with the linear equations for more
conservative RAM usage if wanted.
Aleksi's program with original ruby 1.6.0pre2 garbage collector:
0: 02:28:30.884
1000: 02:28:31.977 1.0938
2000: 02:28:33.926 1.9487
3000: 02:28:36.772 2.8460
4000: 02:28:40.610 3.8377
5000: 02:28:45.309 4.6988
[...]
20000: 02:31:46.021 18.6758
21000: 02:32:04.996 18.9755
22000: 02:32:24.899 19.9027
23000: 02:32:45.754 20.8553
24000: 02:33:08.305 22.5503
With my patch:
0: 02:24:37.112
1000: 02:24:38.061 0.9497
2000: 02:24:39.134 1.0725
3000: 02:24:40.323 1.1893
4000: 02:24:41.468 1.1449
5000: 02:24:42.816 1.3479
[...]
20000: 02:25:03.431 1.1860
21000: 02:25:04.710 1.2786
22000: 02:25:05.992 1.2823
23000: 02:25:08.051 2.0590
24000: 02:25:09.388 1.3363
Here is the patch (it's not beautiful, but it works):
51,69d50
< long allocated_cells = 0;
<
< int
< gc_enough_mallocs_p()
< {
< return malloc_memories > 1000000 + (allocated_cells<<7);
< }
<
< int
< gc_free_min()
< {
< return 4096 + (allocated_cells>>3);
< }
<
< int
< gc_heaps_increment()
< {
< return 8 + (allocated_cells>>16);
< }
92c73
< if (gc_enough_mallocs_p()) {
---
> if (malloc_memories > GC_MALLOC_LIMIT) {
273c254
< heaps_length += gc_heaps_increment();
---
> heaps_length += HEAPS_INCREMENT;
305d285
< allocated_cells++;
714c694
< while (freed < gc_free_min()) {
---
> if (freed < FREE_MIN) {
716d695
< freed += HEAP_SLOTS;
858d836
< allocated_cells--;
923c901
< if (!freelist || gc_enough_mallocs_p()) {
---
> if (!freelist || malloc_memories > GC_MALLOC_LIMIT) {
1260,1265d1237
< static VALUE
< gc_allocated_cells()
< {
< return INT2NUM(allocated_cells);
< }
<
1272d1243
< rb_define_singleton_method(rb_mGC, "allocated_cells", gc_allocated_cells, 0);
matju