From 5081c16bb49a0c9d1dde3cbd7dfb2e97c2827ea4 Mon Sep 17 00:00:00 2001 From: Shirui Cheng Date: Wed, 3 Apr 2024 13:27:11 -0700 Subject: [PATCH] Experimental calloc implementation with using memset on larger sizes --- .../internal/jemalloc_internal_externs.h | 1 + src/arena.c | 35 +++++++++++++++---- src/jemalloc.c | 5 +++ 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/include/jemalloc/internal/jemalloc_internal_externs.h b/include/jemalloc/internal/jemalloc_internal_externs.h index 9d7a9048..41c0f366 100644 --- a/include/jemalloc/internal/jemalloc_internal_externs.h +++ b/include/jemalloc/internal/jemalloc_internal_externs.h @@ -37,6 +37,7 @@ extern const char *const zero_realloc_mode_names[]; extern atomic_zu_t zero_realloc_count; extern bool opt_cache_oblivious; extern unsigned opt_debug_double_free_max_scan; +extern size_t opt_calloc_madvise_threshold; extern const char *opt_malloc_conf_symlink; extern const char *opt_malloc_conf_env_var; diff --git a/src/arena.c b/src/arena.c index 746ab328..8c87d67f 100644 --- a/src/arena.c +++ b/src/arena.c @@ -359,18 +359,39 @@ arena_extent_alloc_large(tsdn_t *tsdn, arena_t *arena, size_t usize, bool guarded = san_large_extent_decide_guard(tsdn, arena_get_ehooks(arena), esize, alignment); - edata_t *edata = pa_alloc(tsdn, &arena->pa_shard, esize, alignment, - /* slab */ false, szind, zero, guarded, &deferred_work_generated); - if (edata != NULL) { - if (config_stats) { - arena_large_malloc_stats_update(tsdn, arena, usize); - } + /* + * - if usize >= opt_calloc_madvise_threshold, + * - pa_alloc(..., zero_override = zero, ...) + * - otherwise, + * - pa_alloc(..., zero_override = false, ...) + * - use memset() to zero out memory if zero == true. + */ + bool zero_override = zero && (usize >= opt_calloc_madvise_threshold); + edata_t *edata = pa_alloc(tsdn, &arena->pa_shard, esize, alignment, + /* slab */ false, szind, zero_override, guarded, + &deferred_work_generated); + + if (edata == NULL) { + return NULL; } - if (edata != NULL && sz_large_pad != 0) { + if (config_stats) { + arena_large_malloc_stats_update(tsdn, arena, usize); + } + if (sz_large_pad != 0) { arena_cache_oblivious_randomize(tsdn, arena, edata, alignment); } + /* + * This branch should be put after the randomization so that the addr + * returned by edata_addr_get() has already be randomized, + * if cache_oblivious is enabled. + */ + if (zero && !zero_override && !edata_zeroed_get(edata)) { + void *addr = edata_addr_get(edata); + size_t usize = edata_usize_get(edata); + memset(addr, 0, usize); + } return edata; } diff --git a/src/jemalloc.c b/src/jemalloc.c index 4e77894c..0362f539 100644 --- a/src/jemalloc.c +++ b/src/jemalloc.c @@ -160,6 +160,8 @@ unsigned ncpus; unsigned opt_debug_double_free_max_scan = SAFETY_CHECK_DOUBLE_FREE_MAX_SCAN_DEFAULT; +size_t opt_calloc_madvise_threshold = 0; + /* Protects arenas initialization. */ static malloc_mutex_t arenas_lock; @@ -1453,6 +1455,9 @@ malloc_conf_init_helper(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS], "debug_double_free_max_scan", 0, UINT_MAX, CONF_DONT_CHECK_MIN, CONF_DONT_CHECK_MAX, /* clip */ false) + CONF_HANDLE_SIZE_T(opt_calloc_madvise_threshold, + "calloc_madvise_threshold", 0, SC_LARGE_MAXCLASS, + CONF_DONT_CHECK_MIN, CONF_CHECK_MAX, /* clip */ false) /* * The runtime option of oversize_threshold remains