Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an option to reduce pagefault when available #430

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions include/mimalloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,9 @@ typedef enum mi_option_e {
mi_option_page_reset,
mi_option_abandoned_page_reset,
mi_option_segment_reset,
#if defined(__linux__)
mi_option_prefault,
#endif
mi_option_eager_commit_delay,
mi_option_reset_delay,
mi_option_use_numa_nodes,
Expand Down
4 changes: 4 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,10 @@ or via environment variables:
`MIMALLOC_EAGER_COMMIT_DELAY=N` (`N` is 1 by default) to delay the initial `N` segments (of 4MiB)
of a thread to not allocate in the huge OS pages; this prevents threads that are short lived
and allocate just a little to take up space in the huge OS page area (which cannot be reset).
- `MIMALLOC_PREFAULT=1`: (Linux only) enable memory prefaulting when available. This option instructs the kernel to synchronously
load the entire mapped region into active memory by specifying `MAP_POPULATE` in `mmap`. It will cause read-ahead on that memory,
and then the subsequent accesses to the memory can proceed without page faults, improving some performance, but might also reduce
some available memory. In `mimalloc_test_stress`, it is known to reduce about 95% page-faults.

Use caution when using `fork` in combination with either large or huge OS pages: on a fork, the OS uses copy-on-write
for all pages in the original process including the huge OS pages. When any memory is now written in that area, the
Expand Down
3 changes: 3 additions & 0 deletions src/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ static mi_option_desc_t options[_mi_option_last] =
{ 1, UNINIT, MI_OPTION(page_reset) }, // reset page memory on free
{ 0, UNINIT, MI_OPTION(abandoned_page_reset) },// reset free page memory when a thread terminates
{ 0, UNINIT, MI_OPTION(segment_reset) }, // reset segment memory on free (needs eager commit)
#if defined(__linux__)
{ 0, UNINIT, MI_OPTION(prefault) },
#endif
#if defined(__NetBSD__)
{ 0, UNINIT, MI_OPTION(eager_commit_delay) }, // the first N segments per thread are not eagerly committed
#else
Expand Down
7 changes: 7 additions & 0 deletions src/os.c
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,10 @@ static void* mi_unix_mmap(void* addr, size_t size, size_t try_alignment, int pro
#define MAP_NORESERVE 0
#endif
int flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE;
#if defined(__linux__)
if (mi_option_get(mi_option_prefault))
flags = flags | MAP_POPULATE;
#endif
int fd = -1;
#if defined(MAP_ALIGNED) // BSD
if (try_alignment > 0) {
Expand Down Expand Up @@ -392,6 +396,9 @@ static void* mi_unix_mmap(void* addr, size_t size, size_t try_alignment, int pro
}
else {
int lflags = flags & ~MAP_NORESERVE; // using NORESERVE on huge pages seems to fail on Linux
#if defined(__linux__)
lflags = lflags & ~MAP_POPULATE; // don't use MAP_POPULATE on huge pages
#endif
int lfd = fd;
#ifdef MAP_ALIGNED_SUPER
lflags |= MAP_ALIGNED_SUPER;
Expand Down