RFR: 8312132: Add tracking of multiple address spaces in NMT

Johan Sjölen jsjolen at openjdk.org
Wed Mar 20 15:05:09 UTC 2024


Hi,

This PR introduces a new abstraction to NMT, named `MemoryFileTracker`. Today, NMT does not track any memory outside of the virtual memory address space. This means that if you allocated memory in something such as a memory-backed file and use `mmap` to map into that memory, then you'll have trouble reporting this to NMT. This is the situation that ZGC is in, and that is what this patch attempts to fix.

## `MemoryFileTracker`

The `MemoryFileTracker` adds the ability of adding new virtual memory address spaces to NMT and committing memory to these, the basic API is:

```c++
    static MemoryFile* make_device(const char* descriptive_name);
    static void free_device(MemoryFile* device);

    static void allocate_memory(MemoryFile* device, size_t offset, size_t size,
                                MEMFLAGS flag, const NativeCallStack& stack);
    static void free_memory(MemoryFile* device, size_t offset, size_t size);


It is easiest to see how this is used by looking at what ZGC's `ZNMT` class does:

```c++
void ZNMT::reserve(zaddress_unsafe start, size_t size) {
  MemTracker::record_virtual_memory_reserve((address)start, size, CALLER_PC, mtJavaHeap);
}
void ZNMT::commit(zoffset offset, size_t size) {
  MemTracker::allocate_memory_in(ZNMT::_device, static_cast<size_t>(offset), size, mtJavaHeap, CALLER_PC);
}
void ZNMT::uncommit(zoffset offset, size_t size) {
  MemTracker::free_memory_in(ZNMT::_device, (size_t)offset, size);
}

void ZNMT::map(zaddress_unsafe addr, size_t size, zoffset offset) {
  // NMT doesn't track mappings at the moment.
}
void ZNMT::unmap(zaddress_unsafe addr, size_t size) {
  // NMT doesn't track mappings at the moment.
}


As you can see, any mapping between reserved regions and device-allocated memory is not recorded in NMT. This means that in detailed mode you only get reserved regions printed for the reserved memory, the device-allocated memory is reported separately. When performing summary reporting any memory allocated via these devices is added to the corresponding `MEMFLAGS` as `committed` memory. 

This patch is also acting as a base on which we deploy multiple new backend ideas to NMT. These ideas are:

1. Implement VMA tracking using a balanced binary tree approach. Today's `VirtualMemoryTracker`'s usage of linked lists is slow and brittle, we'd like to move away from it. Our Treap-based approach in this patch gives a performance boost such that we see 25x better performance in a benchmark. The idea and draft of this is due to Thomas Stüfe, kudos to him.
2. Separate storage of the `NativeCallStack`s in a closed addressing hashtable. NCS:s are large and there are relatively few of them occurring many times, so caching them makes sense. `NCS`:s are never deleted and the bucket array is never resized.


# Example detailed output

We add a section `Memory file details` when producing a detailed report.



Memory file details

Memory map of ZGC heap backing file

[0x0000000000000000 - 0x0000000065200000] allocated 1696595968 for Java Heap
    [0x00007f3ecbdb8aea]ZPhysicalMemoryManager::commit(ZPhysicalMemory&)+0x9a
    [0x00007f3ecbdb211b]ZPageAllocator::commit_page(ZPage*)+0x33
    [0x00007f3ecbdb2ad5]ZPageAllocator::alloc_page_finalize(ZPageAllocation*)+0x7b
    [0x00007f3ecbdb2c1b]ZPageAllocator::alloc_page(ZPageType, unsigned long, ZAllocationFlags, ZPageAge)+0xc7




# Missing features

There is no detailed diffing of this data.

-------------

Commit messages:
 - Use file instead of device
 - Add in atomic.hpp
 - Make some simplifications to TestZNMT
 - Use own PlatformMutex instead
 - Introduce a separate Mutex for MemoryFileTracker
 - Remove comment
 - Delete some code
 - Make addr_cmp belong to VMATree
 - Fix import ordering and adjust printing
 - Revert changes here
 - ... and 19 more: https://git.openjdk.org/jdk/compare/ae5e3fdd...08446455

Changes: https://git.openjdk.org/jdk/pull/18289/files
  Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=18289&range=00
  Issue: https://bugs.openjdk.org/browse/JDK-8312132
  Stats: 1473 lines in 19 files changed: 1370 ins; 84 del; 19 mod
  Patch: https://git.openjdk.org/jdk/pull/18289.diff
  Fetch: git fetch https://git.openjdk.org/jdk.git pull/18289/head:pull/18289

PR: https://git.openjdk.org/jdk/pull/18289


More information about the hotspot-dev mailing list