[plt-scheme] cost of closure?

From: Robby Findler (robby at cs.uchicago.edu)
Date: Thu May 31 22:01:12 EDT 2007

On 5/31/07, Matthew Flatt <mflatt at cs.utah.edu> wrote:
> At Thu, 31 May 2007 16:31:28 -0700, YC wrote:
> > While it's unclear for me what model PLT Scheme uses for structs - Robby
> > alluded to that closures is only a constant factor over struct from memory
> > consumption.
> I think that constant factor should be between 0 and 1 pointer,
> depending on whether the closure refers to top-level bindings or module
> top-level bindings (other than things that are built into MzScheme, in
> which case the reference is inlined instead of kept in the closure).
> Otherwise, a closure has a pointer to its code, and a struct has a
> pointer to it's type descriptor, so those balance; each field and
> captured bindings take the same amount of space.

That wasn't my experience when I was optimizing
define-contract-struct's memory use.

I re-ran an experiment similar to the ones I had run at that time (see
below) and it seems like a 3 field struct is significantly cheaper
than a closure with 3 free variables. But maybe I'm doing something
wrong, or maybe there are other free variables that aren't readily
apparent in the code?

When I run the below I get 42.2 bytes (on average) for 1 cons and 1
3-var closure, as compared to 13.76 bytes (on average) for 1 cons and
one struct. This is according to current-memory-use.


(define (tst mk)
  (define num 100)
  (define ugh1 (begin (collect-garbage) (collect-garbage) (collect-garbage)))
  (define before (current-memory-use))
  (define lst
    (let loop ([n num])
      (unless (zero? n)
        (cons (mk n (+ n 1) (+ n 2))
              (loop (- n 1))))))
  (define ugh2 (begin (collect-garbage) (collect-garbage) (collect-garbage)))
  (define after (current-memory-use))
  (/ (floor (* 100 (/ (- after before) num))) 100.0))

(define-struct s (a b c))
(tst make-s)
(tst (lambda (a b c) (lambda () (a b c))))

Posted on the users mailing list.