ysbaddaden/gc

Resizeable memory maps

Opened this issue · 3 comments

GC_map() currently tells the kernel to allocate as much (virtual) memory as possible, but we could be smarter about it. Instead of asking for as much memory as there are on the computer (thrice), we could tell to map as much as we need, and grow the map as we grow the GC HEAP using mremap(2).

Ideally, we could consider to shrink it after a collect (or once every collect) if we could release a significant amount of memory back to the OS.

Note: allocating so much memory causes issues with Valgrind that intercepts the mmap call and injects the MAP_FIXED flag which tells the kernel to fully allocate memory, which isn't possible and crashes the program (oops).

I hit some issues while trying to implement this:

munmap can shrink a previously allocated mmap, but this is definitive: the memory is no longer accessible (trying to access it will segfault). Despite being capable to pass an address, we can't mmap the released memory again to "grow" the map again. The address is a mere hint and the memory is allocated anywhere (at least on Linux).

mremap should be capable to shrink/grow a mmap, but it's only available in Linux and hidden behind the _GNU_SOURCE flag. It's not portable to anything else (e.g. Darwin, FreeBSD or OpenBSD).

An alternative could be to use sbrk to dynamically grow or shrink the DATA section (beware to copy the original end of the DATA section for the collector to not walk the GC HEAP 😨). It's legacy but should be broadly available.

Except that we need two maps: one for the small objects and another one for the large objects, while sbrk only gives us access to a single one 🤦

We can actually tell the kernel that it can release pages using madvise with the MADV_DONTNEED flag, while still being able to reference that memory later on (which may be the memory as we left it, or be initialized at zero after a page fault).

We can even create "holes" in the memory mapping, as long as we can expect a block header to be initialized at zero this should be fine (at the expense of page faults).