Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
19bbefe
Remove dead code: extent_commit_wrapper, large_salloc, tcache_gc_dall…
spredolac Apr 1, 2026
176ea0a
Remove experimental.thread.activity_callback
spredolac Apr 1, 2026
513778b
Fix off-by-one in arenas_bin_i_index and arenas_lextent_i_index bound…
spredolac Mar 27, 2026
87f9938
Fix duplicate "nactive_huge" JSON key in HPA shard stats output
spredolac Mar 27, 2026
a0f2bdf
Fix missing negation in large_ralloc_no_move usize_min fallback
spredolac Mar 27, 2026
eab2b29
Fix off-by-one in stats_arenas_i_bins_j and stats_arenas_i_lextents_j…
spredolac Mar 27, 2026
c2d5704
Fix out-of-bounds write in malloc_vsnprintf when size is 0
spredolac Mar 27, 2026
3a8bee8
Fix pac_mapped stats inflation on allocation failure
spredolac Mar 27, 2026
dd30c91
Fix wrong fallback value in os_page_detect when sysconf fails
spredolac Mar 27, 2026
3f6e63e
Fix wrong type for malloc_read_fd return value in prof_stack_range
spredolac Mar 27, 2026
675ab07
Fix missing release of acquired neighbor edata in extent_try_coalesce…
spredolac Mar 27, 2026
234404d
Fix wrong loop variable for array index in sz_boot_pind2sz_tab
spredolac Mar 27, 2026
2fceece
Fix extra size argument in edata_init call in extent_alloc_dss
spredolac Mar 27, 2026
5904a42
Fix memory leak of old curr_reg on san_bump_grow_locked failure
spredolac Mar 27, 2026
3ac9f96
Run clang-format on test/unit/conf_parse.c
spredolac Apr 1, 2026
b507644
Fix conf_handle_char_p zero-sized dest and remove unused conf_handle_…
spredolac Mar 27, 2026
a47fa33
Run clang-format on test/unit/tcache_max.c
spredolac Apr 1, 2026
3cc56d3
Fix large alloc nrequests under-counting on cache misses
spredolac Mar 27, 2026
6281482
Nest HPA SEC stats inside hpa_shard JSON
spredolac Mar 27, 2026
db7d997
Add TODO to benchmark possibly better policy
spredolac Mar 27, 2026
f265645
Emit retained HPA slab stats in JSON
spredolac Mar 27, 2026
6515df8
Documentation updates (#2869)
guangli-dai Apr 7, 2026
0aed32b
Merge remote-tracking branch 'origin/dev' into next
azat Apr 9, 2026
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
1 change: 1 addition & 0 deletions Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ TESTS_UNIT := \
$(srcroot)test/unit/junk_alloc.c \
$(srcroot)test/unit/junk_free.c \
$(srcroot)test/unit/json_stats.c \
$(srcroot)test/unit/large_ralloc.c \
$(srcroot)test/unit/log.c \
$(srcroot)test/unit/mallctl.c \
$(srcroot)test/unit/malloc_conf_2.c \
Expand Down
157 changes: 147 additions & 10 deletions doc/jemalloc.xml.in
Original file line number Diff line number Diff line change
Expand Up @@ -897,16 +897,6 @@ mallctl("arena." STRINGIFY(MALLCTL_ARENAS_ALL) ".decay",
during build configuration.</para></listitem>
</varlistentry>

<varlistentry id="config.prof_frameptr">
<term>
<mallctl>config.prof_frameptr</mallctl>
(<type>bool</type>)
<literal>r-</literal>
</term>
<listitem><para><option>--enable-prof-frameptr</option> was specified
during build configuration.</para></listitem>
</varlistentry>

<varlistentry id="config.stats">
<term>
<mallctl>config.stats</mallctl>
Expand Down Expand Up @@ -1419,6 +1409,17 @@ malloc_conf = "xmalloc:true";]]></programlisting>
extent hooks.</para></listitem>
</varlistentry>

<varlistentry id="opt.prof_bt_max">
<term>
<mallctl>opt.prof_bt_max</mallctl>
(<type>unsigned</type>)
<literal>r-</literal>
[<option>--enable-prof</option>]
</term>
<listitem><para>Maximum number of stack frames to record in profiling
backtraces. The default is 128.</para></listitem>
</varlistentry>

<varlistentry id="opt.prof">
<term>
<mallctl>opt.prof</mallctl>
Expand Down Expand Up @@ -1666,6 +1667,53 @@ malloc_conf = "xmalloc:true";]]></programlisting>
testing this behavior.</para></listitem>
</varlistentry>

<varlistentry id="opt.debug_double_free_max_scan">
<term>
<mallctl>opt.debug_double_free_max_scan</mallctl>
(<type>unsigned</type>)
<literal>r-</literal>
[<option>--enable-debug</option>]
</term>
<listitem><para>Maximum number of cached pointers to scan in the
thread cache when checking for double-free errors on deallocation.
When debug is enabled, each deallocation into the tcache scans up to
this many recently cached pointers to detect whether the same pointer
is being freed twice. Setting this to 0 disables the check. This
option is set to 0 and has no effect when debug is not enabled. The
default is 32.</para></listitem>
</varlistentry>

<varlistentry id="opt.disable_large_size_classes">
<term>
<mallctl>opt.disable_large_size_classes</mallctl>
(<type>bool</type>)
<literal>r-</literal>
</term>
<listitem><para>When enabled (the default), large allocations
(i.e. allocations of size &gt;= <constant>SC_LARGE_MINCLASS</constant>)
are rounded up to the nearest page boundary rather than the nearest
large size class. This minimizes memory overhead, especially when
using hugepages, at the cost of disabling the standard large size
class hierarchy.</para></listitem>
</varlistentry>

<varlistentry id="opt.process_madvise_max_batch">
<term>
<mallctl>opt.process_madvise_max_batch</mallctl>
(<type>size_t</type>)
<literal>r-</literal>
</term>
<listitem><para>Maximum number of memory regions to include in each
<citerefentry><refentrytitle>process_madvise</refentrytitle>
<manvolnum>2</manvolnum></citerefentry> batch call. When set to 0
(the default), process_madvise is not used, and the standard
<citerefentry><refentrytitle>madvise</refentrytitle>
<manvolnum>2</manvolnum></citerefentry> is used instead. Setting this
to a positive value enables batched purging via process_madvise, which
can reduce the number of system calls needed for
purging.</para></listitem>
</varlistentry>

<varlistentry id="thread.arena">
<term>
<mallctl>thread.arena</mallctl>
Expand Down Expand Up @@ -1802,6 +1850,47 @@ malloc_conf = "xmalloc:true";]]></programlisting>
the developer may find manual flushing useful.</para></listitem>
</varlistentry>

<varlistentry id="thread.tcache.max">
<term>
<mallctl>thread.tcache.max</mallctl>
(<type>size_t</type>)
<literal>rw</literal>
</term>
<listitem><para>Get or set the maximum cached size class
(<varname>tcache_max</varname>) for the calling thread's tcache. The
value is clamped to the maximum allowed limit and rounded up to the
nearest size class boundary. Changing this value will resize the
thread cache accordingly.</para></listitem>
</varlistentry>

<varlistentry id="thread.tcache.ncached_max.read_sizeclass">
<term>
<mallctl>thread.tcache.ncached_max.read_sizeclass</mallctl>
(<type>size_t</type>)
<literal>rw</literal>
</term>
<listitem><para>Query the maximum number of cached objects
(<varname>ncached_max</varname>) for a given size class in the calling
thread's tcache. The size class is passed in via
<parameter>newp</parameter>, and the corresponding
<varname>ncached_max</varname> is returned via
<parameter>oldp</parameter>.</para></listitem>
</varlistentry>

<varlistentry id="thread.tcache.ncached_max.write">
<term>
<mallctl>thread.tcache.ncached_max.write</mallctl>
(<type>char *</type>)
<literal>-w</literal>
</term>
<listitem><para>Set the maximum number of cached objects
(<varname>ncached_max</varname>) for size classes in the calling
thread's tcache. The input is a string of pipe-separated settings,
where each setting specifies a size range and a count, in the same
format as the <mallctl>opt.tcache_ncached_max</mallctl> runtime
option.</para></listitem>
</varlistentry>

<varlistentry id="thread.prof.name">
<term>
<mallctl>thread.prof.name</mallctl>
Expand Down Expand Up @@ -1985,6 +2074,24 @@ malloc_conf = "xmalloc:true";]]></programlisting>
linkend="thread.arena"><mallctl>thread.arena</mallctl></link>.</para></listitem>
</varlistentry>

<varlistentry id="arena.i.name">
<term>
<mallctl>arena.&lt;i&gt;.name</mallctl>
(<type>char *</type>)
<literal>rw</literal>
</term>
<listitem><para>Get or set a descriptive name for arena &lt;i&gt;.
Arena names can be up to 32 characters long (including the null
terminator); longer names are truncated. When reading, the caller
passes a pointer to a pre-allocated buffer (of at least 32 bytes) via
<parameter>oldp</parameter>, and
<parameter>*oldlenp</parameter> must be
<code language="C">sizeof(<type>char *</type>)</code>.
Arena names are also included in the output of <link
linkend="stats_print"><function>malloc_stats_print()</function></link>.
</para></listitem>
</varlistentry>

<varlistentry id="arena.i.dss">
<term>
<mallctl>arena.&lt;i&gt;.dss</mallctl>
Expand Down Expand Up @@ -2342,6 +2449,18 @@ struct extent_hooks_s {
<listitem><para>Page size.</para></listitem>
</varlistentry>

<varlistentry id="arenas.hugepage">
<term>
<mallctl>arenas.hugepage</mallctl>
(<type>size_t</type>)
<literal>r-</literal>
</term>
<listitem><para>Hugepage size. This value is also reported in the
output of <link
linkend="stats_print"><function>malloc_stats_print()</function></link>.
</para></listitem>
</varlistentry>

<varlistentry id="arenas.tcache_max">
<term>
<mallctl>arenas.tcache_max</mallctl>
Expand Down Expand Up @@ -2561,6 +2680,24 @@ struct extent_hooks_s {
option for additional information.</para></listitem>
</varlistentry>

<varlistentry id="approximate_stats.active">
<term>
<mallctl>approximate_stats.active</mallctl>
(<type>size_t</type>)
<literal>r-</literal>
</term>
<listitem><para>Return the total number of bytes in active pages
collected in an unsynchronized manner, without requiring an
<link linkend="epoch"><mallctl>epoch</mallctl></link> update.
As a result, this value should NOT be compared with other
stats. For example, the relative ordering between
<mallctl>approximate_stats.active</mallctl> and <link
linkend="stats.active"><mallctl>stats.active</mallctl></link> or <link
linkend="stats.resident"><mallctl>stats.resident</mallctl></link> is
not guaranteed. This interface is intended for lightweight monitoring
where an approximate value is sufficient.</para></listitem>
</varlistentry>

<varlistentry id="stats.allocated">
<term>
<mallctl>stats.allocated</mallctl>
Expand Down
26 changes: 0 additions & 26 deletions include/jemalloc/internal/activity_callback.h

This file was deleted.

16 changes: 6 additions & 10 deletions include/jemalloc/internal/conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,15 @@ void malloc_abort_invalid_conf(void);

#ifdef JEMALLOC_JET
extern bool had_conf_error;

bool conf_next(char const **opts_p, char const **k_p, size_t *klen_p,
char const **v_p, size_t *vlen_p);
void conf_error(const char *msg, const char *k, size_t klen,
const char *v, size_t vlen);
void conf_error(
const char *msg, const char *k, size_t klen, const char *v, size_t vlen);
bool conf_handle_bool(const char *v, size_t vlen, bool *result);
bool conf_handle_unsigned(const char *v, size_t vlen,
uintmax_t min, uintmax_t max, bool check_min, bool check_max,
bool clip, uintmax_t *result);
bool conf_handle_signed(const char *v, size_t vlen,
intmax_t min, intmax_t max, bool check_min, bool check_max,
bool clip, intmax_t *result);
bool conf_handle_char_p(const char *v, size_t vlen,
char *dest, size_t dest_sz);
bool conf_handle_signed(const char *v, size_t vlen, intmax_t min, intmax_t max,
bool check_min, bool check_max, bool clip, intmax_t *result);
bool conf_handle_char_p(const char *v, size_t vlen, char *dest, size_t dest_sz);
#endif

#endif /* JEMALLOC_INTERNAL_CONF_H */
2 changes: 0 additions & 2 deletions include/jemalloc/internal/extent.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,6 @@ void extent_dalloc_wrapper_purged(
tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks, edata_t *edata);
void extent_destroy_wrapper(
tsdn_t *tsdn, pac_t *pac, ehooks_t *ehooks, edata_t *edata);
bool extent_commit_wrapper(tsdn_t *tsdn, ehooks_t *ehooks, edata_t *edata,
size_t offset, size_t length);
bool extent_purge_lazy_wrapper(tsdn_t *tsdn, ehooks_t *ehooks, edata_t *edata,
size_t offset, size_t length);
bool extent_purge_forced_wrapper(tsdn_t *tsdn, ehooks_t *ehooks, edata_t *edata,
Expand Down
1 change: 0 additions & 1 deletion include/jemalloc/internal/large_externs.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ void *large_ralloc(tsdn_t *tsdn, arena_t *arena, void *ptr, size_t usize,
void large_dalloc_prep_locked(tsdn_t *tsdn, edata_t *edata);
void large_dalloc_finish(tsdn_t *tsdn, edata_t *edata);
void large_dalloc(tsdn_t *tsdn, edata_t *edata);
size_t large_salloc(tsdn_t *tsdn, const edata_t *edata);
void large_prof_info_get(
tsd_t *tsd, edata_t *edata, prof_info_t *prof_info, bool reset_recent);
void large_prof_tctx_reset(edata_t *edata);
Expand Down
6 changes: 3 additions & 3 deletions include/jemalloc/internal/tcache_inlines.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,10 @@ tcache_alloc_large(tsd_t *tsd, arena_t *arena, tcache_t *tcache, size_t size,
assert(usize <= tcache_max_get(tcache->tcache_slow));
memset(ret, 0, usize);
}
}

if (config_stats) {
bin->tstats.nrequests++;
}
if (config_stats) {
bin->tstats.nrequests++;
}

return ret;
Expand Down
6 changes: 1 addition & 5 deletions include/jemalloc/internal/tsd_internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#define JEMALLOC_INTERNAL_TSD_INTERNALS_H

#include "jemalloc/internal/jemalloc_preamble.h"
#include "jemalloc/internal/activity_callback.h"
#include "jemalloc/internal/arena_types.h"
#include "jemalloc/internal/assert.h"
#include "jemalloc/internal/bin_types.h"
Expand Down Expand Up @@ -84,8 +83,6 @@ typedef ql_elm(tsd_t) tsd_link_t;
O(tsd_link, tsd_link_t, tsd_link_t) \
O(in_hook, bool, bool) \
O(peak, peak_t, peak_t) \
O(activity_callback_thunk, activity_callback_thunk_t, \
activity_callback_thunk_t) \
O(tcache_slow, tcache_slow_t, tcache_slow_t) \
O(rtree_ctx, rtree_ctx_t, rtree_ctx_t)

Expand All @@ -105,8 +102,7 @@ typedef ql_elm(tsd_t) tsd_link_t;
/* sec_shard */ (uint8_t) - 1, \
/* binshards */ TSD_BINSHARDS_ZERO_INITIALIZER, \
/* tsd_link */ {NULL}, /* in_hook */ false, \
/* peak */ PEAK_INITIALIZER, /* activity_callback_thunk */ \
ACTIVITY_CALLBACK_THUNK_INITIALIZER, \
/* peak */ PEAK_INITIALIZER, \
/* tcache_slow */ TCACHE_SLOW_ZERO_INITIALIZER, \
/* rtree_ctx */ RTREE_CTX_INITIALIZER,

Expand Down
3 changes: 3 additions & 0 deletions include/jemalloc/internal/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
*/
#define JEMALLOC_ARG_CONCAT(...) __VA_ARGS__

/* Number of elements in a fixed-size array. */
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))

/* cpp macro definition stringification. */
#define STRINGIFY_HELPER(x) #x
#define STRINGIFY(x) STRINGIFY_HELPER(x)
Expand Down
41 changes: 8 additions & 33 deletions src/conf.c
Original file line number Diff line number Diff line change
Expand Up @@ -254,36 +254,8 @@ JEMALLOC_DIAGNOSTIC_PUSH
JEMALLOC_DIAGNOSTIC_IGNORE("-Wunused-function")

JET_EXTERN bool
conf_handle_unsigned(const char *v, size_t vlen,
uintmax_t min, uintmax_t max, bool check_min, bool check_max,
bool clip, uintmax_t *result) {
char *end;
set_errno(0);
uintmax_t mv = (uintmax_t)malloc_strtoumax(v, &end, 0);
if (get_errno() != 0 || (uintptr_t)end - (uintptr_t)v != vlen) {
return true;
}
if (clip) {
if (check_min && mv < min) {
*result = min;
} else if (check_max && mv > max) {
*result = max;
} else {
*result = mv;
}
} else {
if ((check_min && mv < min) || (check_max && mv > max)) {
return true;
}
*result = mv;
}
return false;
}

JET_EXTERN bool
conf_handle_signed(const char *v, size_t vlen,
intmax_t min, intmax_t max, bool check_min, bool check_max,
bool clip, intmax_t *result) {
conf_handle_signed(const char *v, size_t vlen, intmax_t min, intmax_t max,
bool check_min, bool check_max, bool clip, intmax_t *result) {
char *end;
set_errno(0);
intmax_t mv = (intmax_t)malloc_strtoumax(v, &end, 0);
Expand All @@ -309,6 +281,9 @@ conf_handle_signed(const char *v, size_t vlen,

JET_EXTERN bool
conf_handle_char_p(const char *v, size_t vlen, char *dest, size_t dest_sz) {
if (dest_sz == 0) {
return false;
}
size_t cpylen = (vlen <= dest_sz - 1) ? vlen : dest_sz - 1;
strncpy(dest, v, cpylen);
dest[cpylen] = '\0';
Expand Down Expand Up @@ -473,11 +448,11 @@ malloc_conf_init_helper(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS],
continue;
}

while (*opts != '\0'
&& !conf_next(&opts, &k, &klen, &v, &vlen)) {
while (
*opts != '\0' && !conf_next(&opts, &k, &klen, &v, &vlen)) {
#define CONF_ERROR(msg, k, klen, v, vlen) \
if (!initial_call) { \
conf_error(msg, k, klen, v, vlen); \
conf_error(msg, k, klen, v, vlen); \
cur_opt_valid = false; \
}
#define CONF_CONTINUE \
Expand Down
Loading
Loading