madvise(2)
Advise the kernel how a memory range will be used: free it, page it out, exclude it from dumps.
- Since
- 4.4BSDcheck your kernel →
- glibc
- unknown
- System
- Linux
- Man page
- madvise(2)
Synopsis
#include <sys/mman.h>
int madvise(void addr[size], size_t size, int advice);Rod's take
Your service shows 7 GB RSS, gets OOM-killed, comes back at 800 MB, and somebody files a memory leak ticket. Wrong ticket. Allocators like jemalloc hand freed memory back with MADV_FREE, which lets the kernel reclaim those pages lazily, whenever it gets around to it, and until then they sit in your RSS like ghosts. MADV_DONTNEED drops them on the spot and charges you a page fault on reuse. MADV_FREE is the right call for throughput and a liar for monitoring. Read LazyFree out of smaps_rollup, subtract it, and stop paging people over phantom memory.
Flags and arguments that matter
| Name | What it does |
|---|---|
| MADV_DONTNEED | Drop the pages now: RSS falls immediately; next touch gets zero-fill (private anon) or file contents. |
| MADV_FREELinux 4.5 | Kernel may free the pages lazily under memory pressure; a write before then cancels the free. Private anon only. |
| MADV_DONTDUMPLinux 3.4 | Exclude the range from core dumps; overrides /proc/pid/coredump_filter. |
| MADV_DODUMPLinux 3.4 | Undo an earlier MADV_DONTDUMP. |
| MADV_DONTFORKLinux 2.6.16 | Don't make the range available to the child after fork(2). |
| MADV_WIPEONFORKLinux 4.14 | Child sees zero-filled memory in this range after fork; cleared on execve. Private anon only. |
| MADV_COLDLinux 5.4 | Deactivate the pages so they're likelier reclaim targets. Nondestructive. |
| MADV_PAGEOUTLinux 5.4 | Reclaim the pages now: anon goes to swap, dirty file pages get written back. |
| MADV_HUGEPAGELinux 2.6.38 | Enable transparent huge pages for the range. |
| MADV_POPULATE_WRITELinux 5.14 | Prefault page tables writable, as if writing to each page, without actually writing. |
Errors you will actually hit
| errno | Meaning |
|---|---|
| EINVAL | addr not page-aligned, invalid advice, or advice not allowed on this mapping type (e.g. MADV_FREE on shared). |
| ENOMEM | Part of the range isn't mapped; Linux applies the advice to the rest and still returns this. |
| EAGAIN | A kernel resource was temporarily unavailable. |
| EPERM | MADV_HWPOISON without CAP_SYS_ADMIN. |
| EACCES | MADV_REMOVE on a range that isn't a shared writable mapping. |
Example
# RSS minus MADV_FREE pages the kernel can take back anytime
pid=$(pgrep -n "${1:?usage: $0 <process-name>}")
awk '
/^Rss:/ { rss = $2 }
/^LazyFree:/ { lazy = $2 }
END { printf "rss=%d kB lazy=%d kB committed=%d kB\n", rss, lazy, rss-lazy }
' /proc/$pid/smaps_rollup
# force jemalloc back to immediate MADV_DONTNEED for an honest RSS
MALLOC_CONF="dirty_decay_ms:0,muzzy_decay_ms:0" ./your-serviceTrimmed from the full walkthrough in MADV_FREE and the RSS number that's lying to you.
BSD equivalent
FreeBSD: madvise(2) (4.4BSD) with MADV_FREE and MADV_NOCORE; minherit(2) INHERIT_ZERO for wipe-on-fork. OpenBSD: madvise(2) (since OpenBSD 2.7).
The long version, from the console
Sources
Version numbers are read off the cited man pages, not memory. Spot one that's wrong? Tell Rod.
