[racket] Yet another garbage collection question: major GC cycles

From: Galler (lzgaller at optonline.net)
Date: Fri Feb 15 14:16:38 EST 2013

Dear Racketeers,

*SMALL PREAMBLE*

I'm trying to understand the observed GC behavior so I can create better 
application performance, and I'm focusing on the major GC-cycle.

For usability, my desire would be to have a major-garbage-collection 
cycle last about the same time as a typical request-response cycle, so 
that users experience a maximum  2x normal delay if a request-response 
cyle is interrupted by a major GC-cycle.

Please feel free to direct me to a paper if its simpler.


*THE OBSERVED RACKET BEHAVIOR*

When an application is compiled and run, the garbage collector in v5.3.2 
appears to run through a number of minor collection cycles, then will 
execute two sequential major cycles, in rapid succession.

(I assume this description of behavior is not controversial. For an 
example, please compile and run the source code below.)

The major cycles take a finite amount of time, such duration unrelated 
to the amount of memory cleaned up. This seems consistent with earlier 
descriptions by Matthias that the GC walks through memory looking for 
unreachable code.

The duration of the major cycle seems directly related to the amount of 
memory use by the running application, which again, is consistent with 
prior GC descriptions on this board.

Given the amount of memory usage as an independent vairable, I believe I 
could closely estimate the duration of a major GC cycle (for a specific 
piece of hardware - the constant 3.5ms per 80MB yields good results).

After the major cycles are done, even if no additional user activity 
occurs, the garbage collector will periodically run two sequential major 
cycles, which recover little or no memory.

In contrast, frequency of minor cycles are clearly user-activity 
dependent.

*THE QUESTIONS*

My questions are

1) Why are two successive major cycles neccesary?

2) Why do major cycles occur in the absence of activity? Is there a 
timer associated with major cycles?

3) Is there an optimization going on between amount of memory 
consumption that triggers the first major cycle and Racket's estimate of 
the RATE of memory consumption? (fast as. frequent vs. slow and 
infrequent)

4) is there any rate-related term in the GC algorithm?

5) How does Racket determine how much memory to ask the operating system 
to allocate to an executable?


Thanks

R./
Zack

EXAMPLE CODE

#lang web-server
(require  web-server/servlet-env)

(struct gc-info (major? pre-amount pre-admin-amount code-amount
                         post-amount post-admin-amount
                         start-process-time end-process-time
                         start-time end-time)
   #:prefab)


(define log-rcvr (make-log-receiver (current-logger) 'debug 'GC))

(thread (λ _ (letrec ((rfc (λ _ (let ((gc (vector-ref (sync log-rcvr) 
2)))
                                     (printf "\nMajor cycle:? ~A ; 
cleaned-up ~A MB in ~A ms\n"
                                             (gc-info-major? gc)
                                             (floor (/ (- 
(gc-info-pre-amount gc) (gc-info-post-amount gc)) (* 1024 1024)))
                                             (- 
(gc-info-end-process-time gc) (gc-info-start-process-time gc)))
                                     (rfc)))))
                  (rfc))))


(define (start request)
   (letrec ((response-generator (λ (make-url)
                                  (displayln 'clicky)
                               (response/xexpr `(html (head)
                                                      (body (a ((href 
,(format "~A" (make-url receive-request)))) "click me"))))))
            (receive-request (λ (request)
                               (response/xexpr `(html (head)
                                                      (body "Thank you. 
We are done."))))))
     (send/suspend/dispatch response-generator)))

(serve/servlet start
                #:stateless? #t
                #:launch-browser? #t
                #:connection-close? #t
                #:quit? #f
                #:listen-ip #f
                #:port 8000
                #:servlet-path "/")


Posted on the users mailing list.