popa.bogdanp
2022-5-22 12:25:26

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?


mflatt
2022-5-22 12:38:56

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.


popa.bogdanp
2022-5-22 12:40:22

I see. Thanks!


mflatt
2022-5-22 12:40:40

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.


mflatt
2022-5-22 12:42:12

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.


popa.bogdanp
2022-5-22 13:40:34

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?


mflatt
2022-5-22 14:01:58

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


popa.bogdanp
2022-5-22 14:04:20

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