The collect-maximum-generation-threshold-factor parameter causes the default GC rule to defer a "major" GC — one for the maximum generation — if the number of allocated bytes is less than the parameter's value times the number of allocated bytes just after the previous major GC.
The default value of 2 helps the collector adapt to the scenario that a program has much more long-lived data than short-lived data, and where the program does not explicitly promote its long-lived data to the static generation. This rule reduces run time for one application in Idris by a factor of 3. It improves the GC time for another allocation-intensive application by around 12% (or about 3% of run time). There's a chance that delaying a major GC can retain objects longer, but delaying can also reduce peak memory use by avoiding promotion to the maximum generation. On the whole, there's probably a better rule for any given application, but this one seems to work better for more applications than the existing rule without being a large change to the existing rule.
Here's a program that illustrates in basic terms the intent of the change. On my machine, the timed loop takes half as long after this commit.
(define N (* (expt 2 10) (expt 2 10) 100))
(define M (* (expt 2 10) 100))
(define K 100000)
(define (pointerful n)
(if (< n 128)
(make-vector n)
(cons (pointerful (quotient n 2))
(pointerful (- n (quotient n 2))))))
(define keep (pointerful N))
(time
(let loop ([k K] [v #f])
(unless (zero? k)
(loop (sub1 k)
(pointerful M)))))
The
collect-maximum-generation-threshold-factor
parameter causes the default GC rule to defer a "major" GC — one for the maximum generation — if the number of allocated bytes is less than the parameter's value times the number of allocated bytes just after the previous major GC.The default value of 2 helps the collector adapt to the scenario that a program has much more long-lived data than short-lived data, and where the program does not explicitly promote its long-lived data to the static generation. This rule reduces run time for one application in Idris by a factor of 3. It improves the GC time for another allocation-intensive application by around 12% (or about 3% of run time). There's a chance that delaying a major GC can retain objects longer, but delaying can also reduce peak memory use by avoiding promotion to the maximum generation. On the whole, there's probably a better rule for any given application, but this one seems to work better for more applications than the existing rule without being a large change to the existing rule.
Here's a program that illustrates in basic terms the intent of the change. On my machine, the timed loop takes half as long after this commit.