Skip to content

MmapAllocator assumes 4KB pages; fails on Grace/GH200's default 64KB page size #18617

Description

@karthikeyann

Summary

MmapAllocator assumes the OS page size is 4KB (AllocationTraits::kPageSize, a compile-time constant). On systems where the kernel's actual page size is larger, madvise() calls at sub-page granularity silently fail with EINVAL instead of throwing, which corrupts the allocator's internal page-count accounting (numMapped() can underflow to a huge value) rather than surfacing a clear error. This affects NVIDIA Grace / Grace-Hopper (GH200) systems, where 64KB pages are NVIDIA's documented recommended default (not a rare or misconfigured setup): https://docs.nvidia.com/dccpu/grace-perf-tuning-guide/os-settings.html — "The recommended default value for the page size is 64K."

Root cause

MmapAllocator::SizeClass::adviseAway() calls:

::madvise(run.data(), AllocationTraits::pageBytes(run.numPages()), MADV_DONTNEED)

madvise() requires the address to be aligned to the real OS page size and operates at that granularity. AllocationTraits::kPageSize is hardcoded to 4096 (velox/common/memory/Allocation.h) and used across ~80 call sites in ~27 files to track memory at 4KB-unit granularity — finer than the 64KB pages the kernel actually provides on Grace by default. madvise() on a sub-64KB region fails with EINVAL; the calling code logs the error but doesn't roll back its own accounting, so the allocator's mapped-page counters drift out of sync with reality.

Repro: on a Grace/GH200 host with the default 64KB page kernel (getconf PAGESIZE65536), any code path that calls MmapAllocator::SizeClass::adviseAway() (memory reclaim under pressure, MmapAllocator::unmap(), AsyncDataCache eviction, etc.) hits this. Concretely, MemoryAllocatorTest.unmap and several AsyncDataCacheTest/CacheInputTest cases fail or crash on such a host.

Not Velox-specific

This is a known, currently open, cross-project problem for anything assuming 4KB pages on Grace:

Current mitigation (workaround PR)

See #18619 (draft) for the test-skip workaround this issue tracks a real fix for.

#18618 makes MmapAllocator's constructor check isPageSizeSupported() and fail immediately with a clear, actionable error instead of silently corrupting state, and updates the affected tests to skip (not fail) with an explicit reason when this check doesn't hold. This does not fix the underlying limitation — it converts a silent correctness bug into a loud, honest one, and stops tests from red-flagging a host class that can't be supported without the change described below.

What a real fix looks like

Generalizing AllocationTraits::kPageSize from a compile-time 4096 constant to a value queried at runtime (sysconf(_SC_PAGESIZE)) touches the ~80 call sites above, most of which use it for compile-time-sized bitmap/size-class accounting. Doing this changes MmapAllocator's minimum allocation granularity to match the real page size — on a 64KB-page Grace host that's a 16x increase in the smallest allocatable unit, which has real memory-overhead implications for workloads with many small allocations. That's a deliberate design tradeoff, not a pure bug fix, and needs sign-off from whoever owns the memory-allocator subsystem before landing — hence tracking it here separately rather than folding it into the workaround PR.

Environment where this was found

  • aarch64, NVIDIA GH200 (Grace Hopper), kernel *-64k variant, getconf PAGESIZE = 65536.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions