Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce Thread-local storage variable to reduce atomic contention when update used_memory metrics. #308

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions src/evict.c
Original file line number Diff line number Diff line change
Expand Up @@ -676,12 +676,12 @@ int performEvictions(void) {
* AOF and Output buffer memory will be freed eventually so
* we only care about memory used by the key space. */
enterExecutionUnit(1, 0);
delta = (long long)zmalloc_used_memory();
delta = (long long)zmalloc_used_memory_with_thread_delta();
latencyStartMonitor(eviction_latency);
dbGenericDelete(db, keyobj, server.lazyfree_lazy_eviction, DB_FLAG_KEY_EVICTED);
latencyEndMonitor(eviction_latency);
latencyAddSampleIfNeeded("eviction-del", eviction_latency);
delta -= (long long)zmalloc_used_memory();
delta -= (long long)zmalloc_used_memory_with_thread_delta();
mem_freed += delta;
server.stat_evictedkeys++;
signalModifiedKey(NULL, db, keyobj);
Expand Down
40 changes: 35 additions & 5 deletions src/zmalloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,32 @@ void zlibc_free(void *ptr) {
#define dallocx(ptr, flags) je_dallocx(ptr, flags)
#endif

#define update_zmalloc_stat_alloc(__n) atomic_fetch_add_explicit(&used_memory, (__n), memory_order_relaxed)
#define update_zmalloc_stat_free(__n) atomic_fetch_sub_explicit(&used_memory, (__n), memory_order_relaxed)
#if __STDC_NO_THREADS__
#define thread_local __thread
#else
#include <threads.h>
#endif

static _Atomic int64_t used_memory = 0;
static thread_local int64_t thread_used_memory_delta = 0;

#define THREAD_MEM_MAX_DELTA (1024 * 1024)

static inline void update_zmalloc_stat_alloc(size_t size) {
thread_used_memory_delta += size;
if (thread_used_memory_delta >= THREAD_MEM_MAX_DELTA) {
atomic_fetch_add_explicit(&used_memory, thread_used_memory_delta, memory_order_relaxed);
thread_used_memory_delta = 0;
}
}

static _Atomic size_t used_memory = 0;
static inline void update_zmalloc_stat_free(size_t size) {
thread_used_memory_delta -= size;
if (thread_used_memory_delta <= THREAD_MEM_MAX_DELTA) {
atomic_fetch_add_explicit(&used_memory, thread_used_memory_delta, memory_order_relaxed);
thread_used_memory_delta = 0;
}
}

static void zmalloc_default_oom(size_t size) {
fprintf(stderr, "zmalloc: Out of memory trying to allocate %zu bytes\n", size);
Expand Down Expand Up @@ -388,8 +410,16 @@ char *zstrdup(const char *s) {
}

size_t zmalloc_used_memory(void) {
size_t um = atomic_load_explicit(&used_memory, memory_order_relaxed);
return um;
/* Maybe become negative */
int64_t um = atomic_load_explicit(&used_memory, memory_order_relaxed);
return um < 0 ? 0 : um;
zuiderkwast marked this conversation as resolved.
Show resolved Hide resolved
}

/* Flush the thread_used_memory_delta to global counter. */
size_t zmalloc_used_memory_with_thread_delta(void) {
atomic_fetch_add_explicit(&used_memory, thread_used_memory_delta, memory_order_relaxed);
thread_used_memory_delta = 0;
return zmalloc_used_memory();
}

void zmalloc_set_oom_handler(void (*oom_handler)(size_t)) {
Expand Down
1 change: 1 addition & 0 deletions src/zmalloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ void *ztrycalloc_usable(size_t size, size_t *usable);
void *ztryrealloc_usable(void *ptr, size_t size, size_t *usable);
__attribute__((malloc)) char *zstrdup(const char *s);
size_t zmalloc_used_memory(void);
size_t zmalloc_used_memory_with_thread_delta(void);
void zmalloc_set_oom_handler(void (*oom_handler)(size_t));
size_t zmalloc_get_rss(void);
int zmalloc_get_allocator_info(size_t *allocated,
Expand Down
Loading