From 43a8adc1874d1e910d1fff3d476e9088df0c973f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Schalk=20Kr=C3=BCger?= Date: Fri, 26 Jun 2026 13:53:05 -0700 Subject: [PATCH] Remove experimental_hpa_max_purge_nhp option It is unused and no longer needed: hpa_dirty_mult, hpa_purge_threshold, hpa_min_purge_interval_ms, and hpa_min_purge_delay_ms now provide finer control over the purge rate. --- include/jemalloc/internal/hpa_opts.h | 7 -- src/conf.c | 4 - src/ctl.c | 5 -- src/hpa.c | 16 +--- src/stats.c | 1 - test/stress/pa/pa_microbench.c | 1 - test/unit/hpa.c | 77 +------------------ test/unit/hpa_sec_integration.c | 2 - test/unit/hpa_thp_always.c | 2 - test/unit/hpa_vectorized_madvise.c | 2 - .../unit/hpa_vectorized_madvise_large_batch.c | 2 - test/unit/mallctl.c | 1 - 12 files changed, 2 insertions(+), 118 deletions(-) diff --git a/include/jemalloc/internal/hpa_opts.h b/include/jemalloc/internal/hpa_opts.h index 6747c2db..5c22a34d 100644 --- a/include/jemalloc/internal/hpa_opts.h +++ b/include/jemalloc/internal/hpa_opts.h @@ -108,11 +108,6 @@ struct hpa_shard_opts_s { */ uint64_t min_purge_interval_ms; - /* - * Maximum number of hugepages to purge on each purging attempt. - */ - ssize_t experimental_max_purge_nhp; - /* * Minimum number of inactive bytes needed for a non-empty page to be * considered purgable. @@ -176,8 +171,6 @@ struct hpa_shard_opts_s { false, \ /* min_purge_interval_ms */ \ 5 * 1000, \ - /* experimental_max_purge_nhp */ \ - -1, \ /* size_t purge_threshold */ \ PAGE, \ /* min_purge_delay_ms */ \ diff --git a/src/conf.c b/src/conf.c index e33070b2..50f43a20 100644 --- a/src/conf.c +++ b/src/conf.c @@ -875,10 +875,6 @@ malloc_conf_init_helper(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS], "hpa_min_purge_interval_ms", 0, 0, CONF_DONT_CHECK_MIN, CONF_DONT_CHECK_MAX, false); - CONF_HANDLE_SSIZE_T( - opt_hpa_opts.experimental_max_purge_nhp, - "experimental_hpa_max_purge_nhp", -1, SSIZE_MAX); - /* * Accept either a ratio-based or an exact purge * threshold. diff --git a/src/ctl.c b/src/ctl.c index b94cf22a..193e055a 100644 --- a/src/ctl.c +++ b/src/ctl.c @@ -139,7 +139,6 @@ CTL_PROTO(opt_hpa_hugification_threshold) CTL_PROTO(opt_hpa_hugify_delay_ms) CTL_PROTO(opt_hpa_hugify_sync) CTL_PROTO(opt_hpa_min_purge_interval_ms) -CTL_PROTO(opt_experimental_hpa_max_purge_nhp) CTL_PROTO(opt_hpa_purge_threshold) CTL_PROTO(opt_hpa_min_purge_delay_ms) CTL_PROTO(opt_hpa_hugify_style) @@ -519,8 +518,6 @@ static const ctl_named_node_t opt_node[] = {{NAME("abort"), CTL(opt_abort)}, {NAME("hpa_hugify_delay_ms"), CTL(opt_hpa_hugify_delay_ms)}, {NAME("hpa_hugify_sync"), CTL(opt_hpa_hugify_sync)}, {NAME("hpa_min_purge_interval_ms"), CTL(opt_hpa_min_purge_interval_ms)}, - {NAME("experimental_hpa_max_purge_nhp"), - CTL(opt_experimental_hpa_max_purge_nhp)}, {NAME("hpa_purge_threshold"), CTL(opt_hpa_purge_threshold)}, {NAME("hpa_min_purge_delay_ms"), CTL(opt_hpa_min_purge_delay_ms)}, {NAME("hpa_hugify_style"), CTL(opt_hpa_hugify_style)}, @@ -2241,8 +2238,6 @@ CTL_RO_NL_GEN(opt_hpa_hugify_delay_ms, opt_hpa_opts.hugify_delay_ms, uint64_t) CTL_RO_NL_GEN(opt_hpa_hugify_sync, opt_hpa_opts.hugify_sync, bool) CTL_RO_NL_GEN( opt_hpa_min_purge_interval_ms, opt_hpa_opts.min_purge_interval_ms, uint64_t) -CTL_RO_NL_GEN(opt_experimental_hpa_max_purge_nhp, - opt_hpa_opts.experimental_max_purge_nhp, ssize_t) CTL_RO_NL_GEN(opt_hpa_purge_threshold, opt_hpa_opts.purge_threshold, size_t) CTL_RO_NL_GEN( opt_hpa_min_purge_delay_ms, opt_hpa_opts.min_purge_delay_ms, uint64_t) diff --git a/src/hpa.c b/src/hpa.c index 7613e4d5..29ea9a44 100644 --- a/src/hpa.c +++ b/src/hpa.c @@ -634,22 +634,8 @@ hpa_shard_maybe_do_deferred_work( * too frequently. */ if (hpa_min_purge_interval_passed(tsdn, shard)) { - size_t max_purges = max_ops; - /* - * Limit number of hugepages (slabs) to purge. - * When experimental_max_purge_nhp option is used, there is no - * guarantee we'll always respect dirty_mult option. Option - * experimental_max_purge_nhp provides a way to configure same - * behavior as was possible before, with buggy implementation - * of purging algorithm. - */ - ssize_t max_purge_nhp = shard->opts.experimental_max_purge_nhp; - if (max_purge_nhp != -1 && max_purges > (size_t)max_purge_nhp) { - max_purges = max_purge_nhp; - } - malloc_mutex_assert_owner(tsdn, &shard->mtx); - nops += hpa_purge(tsdn, shard, max_purges); + nops += hpa_purge(tsdn, shard, max_ops); malloc_mutex_assert_owner(tsdn, &shard->mtx); } diff --git a/src/stats.c b/src/stats.c index 6e06bd55..d4b0f4e6 100644 --- a/src/stats.c +++ b/src/stats.c @@ -1774,7 +1774,6 @@ stats_general_print(emitter_t *emitter) { OPT_WRITE_UINT64("hpa_hugify_delay_ms") OPT_WRITE_BOOL("hpa_hugify_sync") OPT_WRITE_UINT64("hpa_min_purge_interval_ms") - OPT_WRITE_SSIZE_T("experimental_hpa_max_purge_nhp") if (je_mallctl("opt.hpa_dirty_mult", (void *)&u32v, &u32sz, NULL, 0) == 0) { /* diff --git a/test/stress/pa/pa_microbench.c b/test/stress/pa/pa_microbench.c index d21576e2..0e6f4276 100644 --- a/test/stress/pa/pa_microbench.c +++ b/test/stress/pa/pa_microbench.c @@ -101,7 +101,6 @@ static hpa_shard_opts_t g_hpa_opts = { /* hugify_delay_ms */ 7804, /* hugify_sync */ false, /* min_purge_interval_ms */ 5 * 1000, - /* experimental_max_purge_nhp */ -1, /* purge_threshold */ HUGEPAGE, /* min_purge_delay_ms */ 0, /* hugify_style */ hpa_hugify_style_eager diff --git a/test/unit/hpa.c b/test/unit/hpa.c index 37eb61b2..a7acab1f 100644 --- a/test/unit/hpa.c +++ b/test/unit/hpa.c @@ -36,8 +36,6 @@ static hpa_shard_opts_t test_hpa_shard_opts_default = { false, /* min_purge_interval_ms */ 5 * 1000, - /* experimental_max_purge_nhp */ - -1, /* purge_threshold */ 1, /* min_purge_delay_ms */ @@ -60,8 +58,6 @@ static hpa_shard_opts_t test_hpa_shard_opts_purge = { false, /* min_purge_interval_ms */ 5 * 1000, - /* experimental_max_purge_nhp */ - -1, /* purge_threshold */ 1, /* min_purge_delay_ms */ @@ -84,8 +80,6 @@ static hpa_shard_opts_t test_hpa_shard_opts_aggressive = { false, /* min_purge_interval_ms */ 5, - /* experimental_max_purge_nhp */ - -1, /* purge_threshold */ HUGEPAGE - 5 * PAGE, /* min_purge_delay_ms */ @@ -636,74 +630,6 @@ TEST_BEGIN(test_purge) { } TEST_END -TEST_BEGIN(test_experimental_max_purge_nhp) { - test_skip_if(!hpa_supported()); - - hpa_hooks_t hooks; - hooks.map = &defer_test_map; - hooks.unmap = &defer_test_unmap; - hooks.purge = &defer_test_purge; - hooks.hugify = &defer_test_hugify; - hooks.dehugify = &defer_test_dehugify; - hooks.curtime = &defer_test_curtime; - hooks.ms_since = &defer_test_ms_since; - hooks.vectorized_purge = &defer_vectorized_purge; - - hpa_shard_opts_t opts = test_hpa_shard_opts_default; - opts.deferral_allowed = true; - opts.experimental_max_purge_nhp = 1; - - hpa_shard_t *shard = create_test_data(&hooks, &opts); - - bool deferred_work_generated = false; - - nstime_init(&defer_curtime, 0); - tsdn_t *tsdn = tsd_tsdn(tsd_fetch()); - enum { NALLOCS = 8 * HUGEPAGE_PAGES }; - edata_t *edatas[NALLOCS]; - for (int i = 0; i < NALLOCS; i++) { - edatas[i] = hpa_alloc(tsdn, shard, PAGE, PAGE, false, - false, false, &deferred_work_generated); - expect_ptr_not_null(edatas[i], "Unexpected null edata"); - } - /* Deallocate 3 hugepages out of 8. */ - for (int i = 0; i < 3 * (int)HUGEPAGE_PAGES; i++) { - hpa_dalloc(tsdn, shard, edatas[i], &deferred_work_generated); - } - nstime_init2(&defer_curtime, 6, 0); - hpa_shard_do_deferred_work(tsdn, shard); - - expect_zu_eq(0, ndefer_hugify_calls, "Hugified too early"); - expect_zu_eq(0, ndefer_dehugify_calls, "Dehugified too early"); - /* - * Expect only one purge call, because opts.experimental_max_purge_nhp - * is set to 1. - */ - expect_zu_eq(1, ndefer_purge_calls, "Expect purges"); - ndefer_purge_calls = 0; - - nstime_init2(&defer_curtime, 12, 0); - hpa_shard_do_deferred_work(tsdn, shard); - - expect_zu_eq(5, ndefer_hugify_calls, "Expect hugification"); - ndefer_hugify_calls = 0; - expect_zu_eq(0, ndefer_dehugify_calls, "Dehugified too early"); - /* We still above the limit for dirty pages. */ - expect_zu_eq(1, ndefer_purge_calls, "Expect purge"); - ndefer_purge_calls = 0; - - nstime_init2(&defer_curtime, 18, 0); - hpa_shard_do_deferred_work(tsdn, shard); - - expect_zu_eq(0, ndefer_hugify_calls, "Hugified too early"); - expect_zu_eq(0, ndefer_dehugify_calls, "Dehugified too early"); - /* Finally, we are below the limit, no purges are expected. */ - expect_zu_eq(0, ndefer_purge_calls, "Purged too early"); - - destroy_test_data(shard); -} -TEST_END - TEST_BEGIN(test_vectorized_opt_eq_zero) { test_skip_if(!hpa_supported() || (opt_process_madvise_max_batch != 0)); @@ -1442,8 +1368,7 @@ main(void) { (void)mem_tree_destroy; return test_no_reentrancy(test_alloc_max, test_stress, test_defer_time, test_purge_no_infinite_loop, test_no_min_purge_interval, - test_min_purge_interval, test_purge, - test_experimental_max_purge_nhp, test_vectorized_opt_eq_zero, + test_min_purge_interval, test_purge, test_vectorized_opt_eq_zero, test_starts_huge, test_start_huge_purge_empty_only, test_assume_huge_purge_fully, test_eager_with_purge_threshold, test_delay_when_not_allowed_deferral, test_deferred_until_time, diff --git a/test/unit/hpa_sec_integration.c b/test/unit/hpa_sec_integration.c index 02cacb9a..b55747ac 100644 --- a/test/unit/hpa_sec_integration.c +++ b/test/unit/hpa_sec_integration.c @@ -36,8 +36,6 @@ static hpa_shard_opts_t test_hpa_shard_opts = { false, /* min_purge_interval_ms */ 5, - /* experimental_max_purge_nhp */ - -1, /* purge_threshold */ PAGE, /* min_purge_delay_ms */ diff --git a/test/unit/hpa_thp_always.c b/test/unit/hpa_thp_always.c index 9fbd55f9..8a8574ab 100644 --- a/test/unit/hpa_thp_always.c +++ b/test/unit/hpa_thp_always.c @@ -36,8 +36,6 @@ static hpa_shard_opts_t test_hpa_shard_opts_aggressive = { false, /* min_purge_interval_ms */ 5, - /* experimental_max_purge_nhp */ - -1, /* purge_threshold */ HUGEPAGE - 5 * PAGE, /* min_purge_delay_ms */ diff --git a/test/unit/hpa_vectorized_madvise.c b/test/unit/hpa_vectorized_madvise.c index e2552ec9..0b5b2474 100644 --- a/test/unit/hpa_vectorized_madvise.c +++ b/test/unit/hpa_vectorized_madvise.c @@ -36,8 +36,6 @@ static hpa_shard_opts_t test_hpa_shard_opts_default = { false, /* min_purge_interval_ms */ 5 * 1000, - /* experimental_max_purge_nhp */ - -1, /* purge_threshold */ 1, /* purge_delay_ms */ diff --git a/test/unit/hpa_vectorized_madvise_large_batch.c b/test/unit/hpa_vectorized_madvise_large_batch.c index ab15b053..47ff2e56 100644 --- a/test/unit/hpa_vectorized_madvise_large_batch.c +++ b/test/unit/hpa_vectorized_madvise_large_batch.c @@ -37,8 +37,6 @@ static hpa_shard_opts_t test_hpa_shard_opts_default = { false, /* min_purge_interval_ms */ 5 * 1000, - /* experimental_max_purge_nhp */ - -1, /* purge_threshold */ 1, /* min_purge_delay_ms */ diff --git a/test/unit/mallctl.c b/test/unit/mallctl.c index c91ec08a..bee7d75a 100644 --- a/test/unit/mallctl.c +++ b/test/unit/mallctl.c @@ -533,7 +533,6 @@ TEST_BEGIN(test_mallctl_opt) { TEST_MALLCTL_OPT(size_t, experimental_pac_sec_nshards, always); TEST_MALLCTL_OPT(size_t, experimental_pac_sec_max_alloc, always); TEST_MALLCTL_OPT(size_t, experimental_pac_sec_max_bytes, always); - TEST_MALLCTL_OPT(ssize_t, experimental_hpa_max_purge_nhp, always); TEST_MALLCTL_OPT(size_t, hpa_purge_threshold, always); TEST_MALLCTL_OPT(uint64_t, hpa_min_purge_delay_ms, always); TEST_MALLCTL_OPT(const char *, hpa_hugify_style, always);