On Linux, Go's page scavenger calls sysUnused once for each candidate range selected by scavengeOne. This normally results in a separate madvise(MADV_FREE) or madvise(MADV_DONTNEED) syscall for each range.
Since Linux 6.13, process_madvise permits these advice values for the caller's own address space and accepts an iovec containing discontiguous ranges. Could the scavenger collect a small, bounded batch of candidate ranges and advise them with one process_madvise call, while retaining the existing per-range madvise path when the syscall or advice is unavailable or denied?
This could reduce syscall overhead on fragmented heaps. Linux 6.16 and later can additionally batch the associated TLB flushes across the vector.
An implementation would need to:
- keep all selected ranges unavailable to allocation until the batch completes;
- use
PIDFD_SELF on Linux 6.15 and later, or a cached self pidfd on Linux 6.13–6.14;
- detect support at runtime and preserve the existing fallback behavior;
- use bounded batches to preserve scavenger pacing and stop points; and
- handle short positive returns from
process_madvise correctly.
I would like to prototype this and benchmark it directly against the current madvise path, using several batch sizes and both MADV_FREE and MADV_DONTNEED, if this direction seems reasonable.
On Linux, Go's page scavenger calls
sysUnusedonce for each candidate range selected byscavengeOne. This normally results in a separatemadvise(MADV_FREE)ormadvise(MADV_DONTNEED)syscall for each range.Since Linux 6.13,
process_madvisepermits these advice values for the caller's own address space and accepts an iovec containing discontiguous ranges. Could the scavenger collect a small, bounded batch of candidate ranges and advise them with oneprocess_madvisecall, while retaining the existing per-rangemadvisepath when the syscall or advice is unavailable or denied?This could reduce syscall overhead on fragmented heaps. Linux 6.16 and later can additionally batch the associated TLB flushes across the vector.
An implementation would need to:
PIDFD_SELFon Linux 6.15 and later, or a cached self pidfd on Linux 6.13–6.14;process_madvisecorrectly.I would like to prototype this and benchmark it directly against the current
madvisepath, using several batch sizes and bothMADV_FREEandMADV_DONTNEED, if this direction seems reasonable.