
In CS, what accounts for the difference between bytes-allocated
and the sum of the sizes of the result of object-counts
? I thought it was that the former returned the total number of bytes in all GC segments, but, looking at the implementation, it only returns the number of bytes in active segments. Adding my own logging to segments.c
, I can see that it’s not unused segments either, since that’s typically a pretty small amount (2–6MB in my tests). The difference <https://gist.github.com/Bogdanp/15d2a650ca6f6fee875a342e85360d5d|seems constant> and I notice that the size of code
as reported by object-counts
is conspicuously small (~10MB for racket/base
), so is the answer that the size of the boot files (roughly 40MB on my machine) isn’t included in the result of object-counts
? Something else?

I think the difference is objects in the “static” generation, which is objects that exist on startup after loading boot files. So, yes, it’s roughly the size of the boot files; it’s more precisely the size of objects created by loading the boot files, but since a lot of that is code that will be the same on disk and in memory, the two end up being similar.

I see. Thanks!

Now that I think about it, Racket uses a vfasl format for boot files, which is closer to a memory image and would bring those sizes even closer together.

Also, if I remember correctly, Chez Scheme’s --enable-object-counts
command-line flag enables object counting for the GC that moves things into the static generation when loading from non-vfasl boot files. I think I also made that work with vfasl by loading the slow way when --enable-object-counts
is on.

Tangentially related to this: I’ve noticed that I can shave off between 5MB (for a program that just requires racket/base
) and 20MB (for one that requires racket/gui
) of RAM by turning off the expander’s module cache. That works out to nearly 10% of all memory used by those programs, so it’s not insignificant (but they’re not exactly good examples of real-world programs).
Would it make sense to expose a function to clear the module cache at the Racket level for programs that want to minimize their memory footprint? Or would that be unsafe? Or could the expander know to clear the cache after the toplevel program has been expanded?

There should be no problem with flushing the expander’s module cache, so exposing that operation would be ok with me.

Cool, I’ll work on that next week. Thanks again!