racket / ChezScheme

Chez Scheme
Apache License 2.0
110 stars 8 forks source link

add `collect-maximum-generation-threshold-factor` #62

Closed mflatt closed 1 year ago

mflatt commented 1 year ago

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)))))