Add opt.thp which allows explicit hugepage usage.
"always" marks all user mappings as MADV_HUGEPAGE; while "never" marks all mappings as MADV_NOHUGEPAGE. The default setting "default" does not change any settings. Note that all the madvise calls are part of the default extent hooks by design, so that customized extent hooks have complete control over the mappings including hugepage settings.
This commit is contained in:
@@ -24,7 +24,8 @@ const char *metadata_thp_mode_names[] = {
|
||||
|
||||
static inline bool
|
||||
metadata_thp_madvise(void) {
|
||||
return (metadata_thp_enabled() && thp_state_madvise);
|
||||
return (metadata_thp_enabled() &&
|
||||
(init_system_thp_mode == thp_mode_default));
|
||||
}
|
||||
|
||||
static void *
|
||||
|
@@ -94,6 +94,7 @@ CTL_PROTO(opt_zero)
|
||||
CTL_PROTO(opt_utrace)
|
||||
CTL_PROTO(opt_xmalloc)
|
||||
CTL_PROTO(opt_tcache)
|
||||
CTL_PROTO(opt_thp)
|
||||
CTL_PROTO(opt_lg_extent_max_active_fit)
|
||||
CTL_PROTO(opt_lg_tcache_max)
|
||||
CTL_PROTO(opt_prof)
|
||||
@@ -292,6 +293,7 @@ static const ctl_named_node_t opt_node[] = {
|
||||
{NAME("utrace"), CTL(opt_utrace)},
|
||||
{NAME("xmalloc"), CTL(opt_xmalloc)},
|
||||
{NAME("tcache"), CTL(opt_tcache)},
|
||||
{NAME("thp"), CTL(opt_thp)},
|
||||
{NAME("lg_extent_max_active_fit"), CTL(opt_lg_extent_max_active_fit)},
|
||||
{NAME("lg_tcache_max"), CTL(opt_lg_tcache_max)},
|
||||
{NAME("prof"), CTL(opt_prof)},
|
||||
@@ -1597,6 +1599,7 @@ CTL_RO_NL_CGEN(config_fill, opt_zero, opt_zero, bool)
|
||||
CTL_RO_NL_CGEN(config_utrace, opt_utrace, opt_utrace, bool)
|
||||
CTL_RO_NL_CGEN(config_xmalloc, opt_xmalloc, opt_xmalloc, bool)
|
||||
CTL_RO_NL_GEN(opt_tcache, opt_tcache, bool)
|
||||
CTL_RO_NL_GEN(opt_thp, thp_mode_names[opt_thp], const char *)
|
||||
CTL_RO_NL_GEN(opt_lg_extent_max_active_fit, opt_lg_extent_max_active_fit,
|
||||
size_t)
|
||||
CTL_RO_NL_GEN(opt_lg_tcache_max, opt_lg_tcache_max, ssize_t)
|
||||
|
12
src/extent.c
12
src/extent.c
@@ -1173,11 +1173,12 @@ extent_alloc_core(tsdn_t *tsdn, arena_t *arena, void *new_addr, size_t size,
|
||||
static void *
|
||||
extent_alloc_default_impl(tsdn_t *tsdn, arena_t *arena, void *new_addr,
|
||||
size_t size, size_t alignment, bool *zero, bool *commit) {
|
||||
void *ret;
|
||||
|
||||
ret = extent_alloc_core(tsdn, arena, new_addr, size, alignment, zero,
|
||||
void *ret = extent_alloc_core(tsdn, arena, new_addr, size, alignment, zero,
|
||||
commit, (dss_prec_t)atomic_load_u(&arena->dss_prec,
|
||||
ATOMIC_RELAXED));
|
||||
if (have_madvise_huge && ret) {
|
||||
pages_set_thp_state(ret, size);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1266,9 +1267,8 @@ extent_grow_retained(tsdn_t *tsdn, arena_t *arena,
|
||||
|
||||
void *ptr;
|
||||
if (*r_extent_hooks == &extent_hooks_default) {
|
||||
ptr = extent_alloc_core(tsdn, arena, NULL, alloc_size, PAGE,
|
||||
&zeroed, &committed, (dss_prec_t)atomic_load_u(
|
||||
&arena->dss_prec, ATOMIC_RELAXED));
|
||||
ptr = extent_alloc_default_impl(tsdn, arena, NULL,
|
||||
alloc_size, PAGE, &zeroed, &committed);
|
||||
} else {
|
||||
extent_hook_pre_reentrancy(tsdn, arena);
|
||||
ptr = (*r_extent_hooks)->alloc(*r_extent_hooks, NULL,
|
||||
|
@@ -1152,9 +1152,8 @@ malloc_conf_init(void) {
|
||||
CONF_HANDLE_SSIZE_T(opt_lg_tcache_max, "lg_tcache_max",
|
||||
-1, (sizeof(size_t) << 3) - 1)
|
||||
if (strncmp("percpu_arena", k, klen) == 0) {
|
||||
int i;
|
||||
bool match = false;
|
||||
for (i = percpu_arena_mode_names_base; i <
|
||||
for (int i = percpu_arena_mode_names_base; i <
|
||||
percpu_arena_mode_names_limit; i++) {
|
||||
if (strncmp(percpu_arena_mode_names[i],
|
||||
v, vlen) == 0) {
|
||||
@@ -1204,6 +1203,27 @@ malloc_conf_init(void) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (CONF_MATCH("thp")) {
|
||||
bool match = false;
|
||||
for (int i = 0; i < thp_mode_names_limit; i++) {
|
||||
if (strncmp(thp_mode_names[i],v, vlen)
|
||||
== 0) {
|
||||
if (!have_madvise_huge) {
|
||||
malloc_conf_error(
|
||||
"No THP support",
|
||||
k, klen, v, vlen);
|
||||
}
|
||||
opt_thp = i;
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!match) {
|
||||
malloc_conf_error("Invalid conf value",
|
||||
k, klen, v, vlen);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
malloc_conf_error("Invalid conf pair", k, klen, v,
|
||||
vlen);
|
||||
#undef CONF_MATCH
|
||||
|
88
src/pages.c
88
src/pages.c
@@ -28,7 +28,14 @@ static int mmap_flags;
|
||||
#endif
|
||||
static bool os_overcommits;
|
||||
|
||||
bool thp_state_madvise;
|
||||
const char *thp_mode_names[] = {
|
||||
"default",
|
||||
"always",
|
||||
"never",
|
||||
"not supported"
|
||||
};
|
||||
thp_mode_t opt_thp = THP_MODE_DEFAULT;
|
||||
thp_mode_t init_system_thp_mode;
|
||||
|
||||
/* Runtime support for lazy purge. Irrelevant when !pages_can_purge_lazy. */
|
||||
static bool pages_can_purge_lazy_runtime = true;
|
||||
@@ -307,11 +314,12 @@ pages_purge_forced(void *addr, size_t size) {
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
pages_huge(void *addr, size_t size) {
|
||||
assert(HUGEPAGE_ADDR2BASE(addr) == addr);
|
||||
assert(HUGEPAGE_CEILING(size) == size);
|
||||
|
||||
static bool
|
||||
pages_huge_impl(void *addr, size_t size, bool aligned) {
|
||||
if (aligned) {
|
||||
assert(HUGEPAGE_ADDR2BASE(addr) == addr);
|
||||
assert(HUGEPAGE_CEILING(size) == size);
|
||||
}
|
||||
#ifdef JEMALLOC_HAVE_MADVISE_HUGE
|
||||
return (madvise(addr, size, MADV_HUGEPAGE) != 0);
|
||||
#else
|
||||
@@ -320,9 +328,21 @@ pages_huge(void *addr, size_t size) {
|
||||
}
|
||||
|
||||
bool
|
||||
pages_nohuge(void *addr, size_t size) {
|
||||
assert(HUGEPAGE_ADDR2BASE(addr) == addr);
|
||||
assert(HUGEPAGE_CEILING(size) == size);
|
||||
pages_huge(void *addr, size_t size) {
|
||||
return pages_huge_impl(addr, size, true);
|
||||
}
|
||||
|
||||
static bool
|
||||
pages_huge_unaligned(void *addr, size_t size) {
|
||||
return pages_huge_impl(addr, size, false);
|
||||
}
|
||||
|
||||
static bool
|
||||
pages_nohuge_impl(void *addr, size_t size, bool aligned) {
|
||||
if (aligned) {
|
||||
assert(HUGEPAGE_ADDR2BASE(addr) == addr);
|
||||
assert(HUGEPAGE_CEILING(size) == size);
|
||||
}
|
||||
|
||||
#ifdef JEMALLOC_HAVE_MADVISE_HUGE
|
||||
return (madvise(addr, size, MADV_NOHUGEPAGE) != 0);
|
||||
@@ -331,6 +351,16 @@ pages_nohuge(void *addr, size_t size) {
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
pages_nohuge(void *addr, size_t size) {
|
||||
return pages_nohuge_impl(addr, size, true);
|
||||
}
|
||||
|
||||
static bool
|
||||
pages_nohuge_unaligned(void *addr, size_t size) {
|
||||
return pages_nohuge_impl(addr, size, false);
|
||||
}
|
||||
|
||||
bool
|
||||
pages_dontdump(void *addr, size_t size) {
|
||||
assert(PAGE_ADDR2BASE(addr) == addr);
|
||||
@@ -469,6 +499,25 @@ os_overcommits_proc(void) {
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
pages_set_thp_state (void *ptr, size_t size) {
|
||||
if (opt_thp == thp_mode_default || opt_thp == init_system_thp_mode) {
|
||||
return;
|
||||
}
|
||||
assert(opt_thp != thp_mode_not_supported &&
|
||||
init_system_thp_mode != thp_mode_not_supported);
|
||||
|
||||
if (opt_thp == thp_mode_always
|
||||
&& init_system_thp_mode != thp_mode_never) {
|
||||
assert(init_system_thp_mode == thp_mode_default);
|
||||
pages_huge_unaligned(ptr, size);
|
||||
} else if (opt_thp == thp_mode_never) {
|
||||
assert(init_system_thp_mode == thp_mode_default ||
|
||||
init_system_thp_mode == thp_mode_always);
|
||||
pages_nohuge_unaligned(ptr, size);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
init_thp_state(void) {
|
||||
if (!have_madvise_huge) {
|
||||
@@ -479,8 +528,10 @@ init_thp_state(void) {
|
||||
goto label_error;
|
||||
}
|
||||
|
||||
static const char madvise_state[] = "always [madvise] never\n";
|
||||
char buf[sizeof(madvise_state)];
|
||||
static const char sys_state_madvise[] = "always [madvise] never\n";
|
||||
static const char sys_state_always[] = "[always] madvise never\n";
|
||||
static const char sys_state_never[] = "always madvise [never]\n";
|
||||
char buf[sizeof(sys_state_madvise)];
|
||||
|
||||
#if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_open)
|
||||
int fd = (int)syscall(SYS_open,
|
||||
@@ -504,15 +555,18 @@ init_thp_state(void) {
|
||||
close(fd);
|
||||
#endif
|
||||
|
||||
if (nread < 1) {
|
||||
if (strncmp(buf, sys_state_madvise, (size_t)nread) == 0) {
|
||||
init_system_thp_mode = thp_mode_default;
|
||||
} else if (strncmp(buf, sys_state_always, (size_t)nread) == 0) {
|
||||
init_system_thp_mode = thp_mode_always;
|
||||
} else if (strncmp(buf, sys_state_never, (size_t)nread) == 0) {
|
||||
init_system_thp_mode = thp_mode_never;
|
||||
} else {
|
||||
goto label_error;
|
||||
}
|
||||
if (strncmp(buf, madvise_state, (size_t)nread) == 0) {
|
||||
thp_state_madvise = true;
|
||||
return;
|
||||
}
|
||||
return;
|
||||
label_error:
|
||||
thp_state_madvise = false;
|
||||
opt_thp = init_system_thp_mode = thp_mode_not_supported;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@@ -837,6 +837,7 @@ stats_general_print(void (*write_cb)(void *, const char *), void *cbopaque,
|
||||
OPT_WRITE_BOOL(xmalloc, ",")
|
||||
OPT_WRITE_BOOL(tcache, ",")
|
||||
OPT_WRITE_SSIZE_T(lg_tcache_max, ",")
|
||||
OPT_WRITE_CHAR_P(thp, ",")
|
||||
OPT_WRITE_BOOL(prof, ",")
|
||||
OPT_WRITE_CHAR_P(prof_prefix, ",")
|
||||
OPT_WRITE_BOOL_MUTABLE(prof_active, prof.active, ",")
|
||||
|
Reference in New Issue
Block a user