Skip to content

Commit b27dbaa

Browse files
committed
Reduce the overhead from malloc usable
1 parent 5582a41 commit b27dbaa

File tree

4 files changed

+69
-21
lines changed

4 files changed

+69
-21
lines changed

deps/jemalloc/include/jemalloc/internal/jemalloc_internal_externs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,6 @@ void jemalloc_prefork(void);
7070
void jemalloc_postfork_parent(void);
7171
void jemalloc_postfork_child(void);
7272
void je_sdallocx_noflags(void *ptr, size_t size);
73-
void *malloc_default(size_t size);
73+
void *malloc_default(size_t size, size_t *usable_sz);
7474

7575
#endif /* JEMALLOC_INTERNAL_EXTERNS_H */

deps/jemalloc/include/jemalloc/internal/jemalloc_internal_inlines_c.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -255,15 +255,15 @@ malloc_initialized(void) {
255255
* tail-call to the slowpath if they fire.
256256
*/
257257
JEMALLOC_ALWAYS_INLINE void *
258-
imalloc_fastpath(size_t size, void *(fallback_alloc)(size_t)) {
258+
imalloc_fastpath(size_t size, size_t *usable_sz, void *(fallback_alloc)(size_t, size_t *)) {
259259
LOG("core.malloc.entry", "size: %zu", size);
260260
if (tsd_get_allocates() && unlikely(!malloc_initialized())) {
261-
return fallback_alloc(size);
261+
return fallback_alloc(size, usable_sz);
262262
}
263263

264264
tsd_t *tsd = tsd_get(false);
265265
if (unlikely((size > SC_LOOKUP_MAXCLASS) || tsd == NULL)) {
266-
return fallback_alloc(size);
266+
return fallback_alloc(size, usable_sz);
267267
}
268268
/*
269269
* The code below till the branch checking the next_event threshold may
@@ -307,7 +307,7 @@ imalloc_fastpath(size_t size, void *(fallback_alloc)(size_t)) {
307307
* 0) in a single branch.
308308
*/
309309
if (unlikely(allocated_after >= threshold)) {
310-
return fallback_alloc(size);
310+
return fallback_alloc(size, usable_sz);
311311
}
312312
assert(tsd_fast(tsd));
313313

@@ -316,6 +316,7 @@ imalloc_fastpath(size_t size, void *(fallback_alloc)(size_t)) {
316316
cache_bin_t *bin = &tcache->bins[ind];
317317
bool tcache_success;
318318
void *ret;
319+
if (usable_sz) *usable_sz = usize;
319320

320321
/*
321322
* We split up the code this way so that redundant low-water
@@ -334,7 +335,7 @@ imalloc_fastpath(size_t size, void *(fallback_alloc)(size_t)) {
334335
return ret;
335336
}
336337

337-
return fallback_alloc(size);
338+
return fallback_alloc(size, usable_sz);
338339
}
339340

340341
JEMALLOC_ALWAYS_INLINE int

deps/jemalloc/src/jemalloc.c

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2697,7 +2697,7 @@ imalloc(static_opts_t *sopts, dynamic_opts_t *dopts) {
26972697

26982698
JEMALLOC_NOINLINE
26992699
void *
2700-
malloc_default(size_t size) {
2700+
malloc_default(size_t size, size_t *usize) {
27012701
void *ret;
27022702
static_opts_t sopts;
27032703
dynamic_opts_t dopts;
@@ -2731,6 +2731,7 @@ malloc_default(size_t size) {
27312731

27322732
LOG("core.malloc.exit", "result: %p", ret);
27332733

2734+
if (usize) *usize = dopts.usize;
27342735
return ret;
27352736
}
27362737

@@ -2743,9 +2744,11 @@ JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
27432744
void JEMALLOC_NOTHROW *
27442745
JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1)
27452746
je_malloc(size_t size) {
2746-
return imalloc_fastpath(size, &malloc_default);
2747+
return imalloc_fastpath(size, NULL, &malloc_default);
27472748
}
27482749

2750+
2751+
27492752
JEMALLOC_EXPORT int JEMALLOC_NOTHROW
27502753
JEMALLOC_ATTR(nonnull(1))
27512754
je_posix_memalign(void **memptr, size_t alignment, size_t size) {
@@ -2861,7 +2864,7 @@ je_calloc(size_t num, size_t size) {
28612864
}
28622865

28632866
JEMALLOC_ALWAYS_INLINE void
2864-
ifree(tsd_t *tsd, void *ptr, tcache_t *tcache, bool slow_path) {
2867+
ifree(tsd_t *tsd, void *ptr, tcache_t *tcache, bool slow_path, size_t *usable) {
28652868
if (!slow_path) {
28662869
tsd_assert_fast(tsd);
28672870
}
@@ -2894,6 +2897,7 @@ ifree(tsd_t *tsd, void *ptr, tcache_t *tcache, bool slow_path) {
28942897
true);
28952898
}
28962899
thread_dalloc_event(tsd, usize);
2900+
if (usable) *usable = usize;
28972901
}
28982902

28992903
JEMALLOC_ALWAYS_INLINE bool
@@ -2993,7 +2997,7 @@ isfree(tsd_t *tsd, void *ptr, size_t usize, tcache_t *tcache, bool slow_path) {
29932997

29942998
JEMALLOC_NOINLINE
29952999
void
2996-
free_default(void *ptr) {
3000+
free_default(void *ptr, size_t *usable) {
29973001
UTRACE(ptr, 0, 0);
29983002
if (likely(ptr != NULL)) {
29993003
/*
@@ -3011,14 +3015,14 @@ free_default(void *ptr) {
30113015
tcache_t *tcache = tcache_get_from_ind(tsd,
30123016
TCACHE_IND_AUTOMATIC, /* slow */ false,
30133017
/* is_alloc */ false);
3014-
ifree(tsd, ptr, tcache, /* slow */ false);
3018+
ifree(tsd, ptr, tcache, /* slow */ false, usable);
30153019
} else {
30163020
tcache_t *tcache = tcache_get_from_ind(tsd,
30173021
TCACHE_IND_AUTOMATIC, /* slow */ true,
30183022
/* is_alloc */ false);
30193023
uintptr_t args_raw[3] = {(uintptr_t)ptr};
30203024
hook_invoke_dalloc(hook_dalloc_free, ptr, args_raw);
3021-
ifree(tsd, ptr, tcache, /* slow */ true);
3025+
ifree(tsd, ptr, tcache, /* slow */ true, usable);
30223026
}
30233027

30243028
check_entry_exit_locking(tsd_tsdn(tsd));
@@ -3062,7 +3066,7 @@ free_fastpath_nonfast_aligned(void *ptr, bool check_prof) {
30623066

30633067
/* Returns whether or not the free attempt was successful. */
30643068
JEMALLOC_ALWAYS_INLINE
3065-
bool free_fastpath(void *ptr, size_t size, bool size_hint) {
3069+
bool free_fastpath(void *ptr, size_t size, bool size_hint, size_t *usable) {
30663070
tsd_t *tsd = tsd_get(false);
30673071
/* The branch gets optimized away unless tsd_get_allocates(). */
30683072
if (unlikely(tsd == NULL)) {
@@ -3116,6 +3120,7 @@ bool free_fastpath(void *ptr, size_t size, bool size_hint) {
31163120
te_free_fastpath_ctx(tsd, &deallocated, &threshold);
31173121

31183122
size_t usize = sz_index2size(alloc_ctx.szind);
3123+
if (usable) *usable = usize;
31193124
uint64_t deallocated_after = deallocated + usize;
31203125
/*
31213126
* Check for events and tsd non-nominal (fast_threshold will be set to
@@ -3158,8 +3163,8 @@ JEMALLOC_EXPORT void JEMALLOC_NOTHROW
31583163
je_free(void *ptr) {
31593164
LOG("core.free.entry", "ptr: %p", ptr);
31603165

3161-
if (!free_fastpath(ptr, 0, false)) {
3162-
free_default(ptr);
3166+
if (!free_fastpath(ptr, 0, false, NULL)) {
3167+
free_default(ptr, NULL);
31633168
}
31643169

31653170
LOG("core.free.exit", "");
@@ -3601,7 +3606,7 @@ do_realloc_nonnull_zero(void *ptr) {
36013606
/* is_alloc */ false);
36023607
uintptr_t args[3] = {(uintptr_t)ptr, 0};
36033608
hook_invoke_dalloc(hook_dalloc_realloc, ptr, args);
3604-
ifree(tsd, ptr, tcache, true);
3609+
ifree(tsd, ptr, tcache, true, NULL);
36053610

36063611
check_entry_exit_locking(tsd_tsdn(tsd));
36073612
return NULL;
@@ -3883,11 +3888,11 @@ je_dallocx(void *ptr, int flags) {
38833888
UTRACE(ptr, 0, 0);
38843889
if (likely(fast)) {
38853890
tsd_assert_fast(tsd);
3886-
ifree(tsd, ptr, tcache, false);
3891+
ifree(tsd, ptr, tcache, false, NULL);
38873892
} else {
38883893
uintptr_t args_raw[3] = {(uintptr_t)ptr, flags};
38893894
hook_invoke_dalloc(hook_dalloc_dallocx, ptr, args_raw);
3890-
ifree(tsd, ptr, tcache, true);
3895+
ifree(tsd, ptr, tcache, true, NULL);
38913896
}
38923897
check_entry_exit_locking(tsd_tsdn(tsd));
38933898

@@ -3935,7 +3940,7 @@ je_sdallocx(void *ptr, size_t size, int flags) {
39353940
LOG("core.sdallocx.entry", "ptr: %p, size: %zu, flags: %d", ptr,
39363941
size, flags);
39373942

3938-
if (flags != 0 || !free_fastpath(ptr, size, true)) {
3943+
if (flags != 0 || !free_fastpath(ptr, size, true, NULL)) {
39393944
sdallocx_default(ptr, size, flags);
39403945
}
39413946

@@ -3947,7 +3952,7 @@ je_sdallocx_noflags(void *ptr, size_t size) {
39473952
LOG("core.sdallocx.entry", "ptr: %p, size: %zu, flags: 0", ptr,
39483953
size);
39493954

3950-
if (!free_fastpath(ptr, size, true)) {
3955+
if (!free_fastpath(ptr, size, true, NULL)) {
39513956
sdallocx_default(ptr, size, 0);
39523957
}
39533958

@@ -4483,3 +4488,21 @@ get_defrag_hint(void* ptr) {
44834488
assert(ptr != NULL);
44844489
return iget_defrag_hint(TSDN_NULL, ptr);
44854490
}
4491+
4492+
JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
4493+
void JEMALLOC_NOTHROW *
4494+
JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1)
4495+
malloc_usable(size_t size, size_t *usize) {
4496+
return imalloc_fastpath(size, usize, &malloc_default);
4497+
}
4498+
4499+
JEMALLOC_EXPORT void JEMALLOC_NOTHROW
4500+
free_usable(void *ptr, size_t *usable) {
4501+
LOG("core.free.entry", "ptr: %p", ptr);
4502+
4503+
if (!free_fastpath(ptr, 0, false, usable)) {
4504+
free_default(ptr, usable);
4505+
}
4506+
4507+
LOG("core.free.exit", "");
4508+
}

src/zmalloc.c

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ void zlibc_free(void *ptr) {
5151
*/
5252
#define MALLOC_MIN_SIZE(x) ((x) > 0 ? (x) : sizeof(long))
5353

54+
void *je_malloc_usable(size_t size, size_t *usable);
55+
void je_free_usable(void *ptr, size_t *usable);
56+
5457
/* Explicitly override malloc/free etc when using tcmalloc. */
5558
#if defined(USE_TCMALLOC)
5659
#define malloc(size) tc_malloc(size)
@@ -116,13 +119,21 @@ void *extend_to_usable(void *ptr, size_t size) {
116119
/* Try allocating memory, and return NULL if failed.
117120
* '*usable' is set to the usable size if non NULL. */
118121
static inline void *ztrymalloc_usable_internal(size_t size, size_t *usable) {
122+
size_t usize = 0;
119123
/* Possible overflow, return NULL, so that the caller can panic or handle a failed allocation. */
120124
if (size >= SIZE_MAX/2) return NULL;
125+
#if defined(USE_JEMALLOC)
126+
void *ptr = je_malloc_usable(MALLOC_MIN_SIZE(size)+PREFIX_SIZE, &usize);
127+
#else
121128
void *ptr = malloc(MALLOC_MIN_SIZE(size)+PREFIX_SIZE);
122-
129+
#endif
123130
if (!ptr) return NULL;
124131
#ifdef HAVE_MALLOC_SIZE
132+
#if defined(USE_JEMALLOC)
125133
size = zmalloc_size(ptr);
134+
#else
135+
size = usize;
136+
#endif
126137
update_zmalloc_stat_alloc(size);
127138
if (usable) *usable = size;
128139
return ptr;
@@ -423,8 +434,14 @@ void zfree(void *ptr) {
423434

424435
if (ptr == NULL) return;
425436
#ifdef HAVE_MALLOC_SIZE
437+
#if defined(USE_JEMALLOC)
438+
size_t usize = 0;
439+
je_free_usable(ptr, &usize);
440+
update_zmalloc_stat_free(usize);
441+
#else
426442
update_zmalloc_stat_free(zmalloc_size(ptr));
427443
free(ptr);
444+
#endif
428445
#else
429446
realptr = (char*)ptr-PREFIX_SIZE;
430447
oldsize = *((size_t*)realptr);
@@ -442,8 +459,15 @@ void zfree_usable(void *ptr, size_t *usable) {
442459

443460
if (ptr == NULL) return;
444461
#ifdef HAVE_MALLOC_SIZE
462+
#if defined(USE_JEMALLOC)
463+
size_t usize = 0;
464+
je_free_usable(ptr, &usize);
465+
update_zmalloc_stat_free(usize);
466+
*usable = usize;
467+
#else
445468
update_zmalloc_stat_free(*usable = zmalloc_size(ptr));
446469
free(ptr);
470+
#endif
447471
#else
448472
realptr = (char*)ptr-PREFIX_SIZE;
449473
*usable = oldsize = *((size_t*)realptr);

0 commit comments

Comments
 (0)