-
Notifications
You must be signed in to change notification settings - Fork 78
Description
Currently, in both Map32 and Map64, we assume MMTk occupies a predefined memory range. The default range for Map32 is 0x8000_0000 to 0xd000_0000, and the default range for Map64 is 0x200_0000_0000 to 0x2200_0000_0000. The generous supply of heap space allows Map64 to implement SFT efficiently, and allows all side metadata to be stored contiguously.
But in real-world applications, MMTk is not free to use the entire address space. The application may arrange its address space for its own specific need, and multiple MMTk instances will compete for the same address range.
I propose we introduce external memory sources to MMTk so that it can request memory from external sources, e.g. the OS via the mmap
syscall, or the VM.
Update: Alternatively, MMTk can inspect the /proc/pid/maps and figure out one (or more) proper memory range(s). That is equivalent to calling mmap
and letting the OS decide for MMTk.
Note: This is not intended to replace the existing Map32
or Map64
, but provide a complement to those.
Existing approaches
CRuby's default GC
CRuby's default GC organizes the heap into 64KB blocks (CRuby calls it "page", but I'll keep using the term "block" to be consistent with MMTk). Each individual block is allocated from mmap
or posix_memalign
. CRuby maintains both arrays and linked lists of blocks for different purposes. The side metadata are stored in the beginning of each block. (Note that CRuby's max object size is 640B, so a 64K block is almost as big as a chunk for CRuby.)
I am not suggesting that MMTk should externalize the allocation of blocks. It would be too inefficient if we call mmap
that often.
OpenJDK
TODO
Suggested interface
trait ExternalChunkResource {
/// Allocate contiguous range of `num_chunks` chunks. Must be aligned to chunk.
fn allocate_contiguous_chunks(num_chunks: usize) -> Option<Address>;
/// Free an allocated contiguous range of chunks.
fn free_contiguous_chunks(chunk_group: Address);
}
It should be as simple as that, and that's essentially what Map32
does. mmtk-core will have to maintain its own list/array/vector of acquired "contiguous chunkses", which is currently done by Map32Inner::prev_link
and Map32Inner::next_link
.
Using this approach, all side metadata will have to be discontiguous, including global metadata. Then "global" will simply mean it exists in every space, but a global side metadata may end up being in each chunk.
We can still have SFT and a chunk-grained Mmapper (or more precisely a MapStateStorage
as described in #1345) because the interface demands the chunks are aligned. We can still implement is_mmtk_object
using SFT and Mmapper, or alternatively we can do linear or binary search on allocated "contiguous chunkses" to find the chunk an address belongs to.
FreeListPageResource
may need to be re-implemented so that it no longer assumes all chunks in all spaces form a contiguous memory range. Alternatively we replace FreeListPageResource
with something else.
Alternatives
(Update) As we discussed, there is an important alternative to the above. We dynamically select the memory range at MMTk initialization time (either by looking at /proc/pid/maps
or letting an external entity (such as the OS via mmap
) decide the range), but we only request one contiguous range for MMTk's heap instead of requesting many discontiguous ranges on demand. This should be easier to implement and gives MMTk more control over the memory range, and makes certain things easier (such as side metadata). As a tradeoff, once the range is determined, it cannot be extended at run time.