From 37cb1268123e2992c194f9ef0e83a27b06b278cf Mon Sep 17 00:00:00 2001 From: Cloud Date: Mon, 28 Apr 2014 13:48:50 +0800 Subject: [PATCH] Not use jemalloc on macosx, See Issue #99 --- Makefile | 7 +- platform.mk | 3 + skynet-src/malloc_hook.c | 239 ++++++++++++++++++++++++--------------- 3 files changed, 153 insertions(+), 96 deletions(-) diff --git a/Makefile b/Makefile index d8745075..28361727 100644 --- a/Makefile +++ b/Makefile @@ -22,6 +22,7 @@ JEMALLOC_STATICLIB := 3rd/jemalloc/lib/libjemalloc_pic.a JEMALLOC_INC := 3rd/jemalloc/include/jemalloc all : jemalloc + .PHONY : jemalloc $(JEMALLOC_STATICLIB) : 3rd/jemalloc/Makefile @@ -33,7 +34,7 @@ $(JEMALLOC_STATICLIB) : 3rd/jemalloc/Makefile 3rd/jemalloc/Makefile : | 3rd/jemalloc/autogen.sh cd 3rd/jemalloc && ./autogen.sh --with-jemalloc-prefix=je_ --disable-valgrind -jemalloc : $(JEMALLOC_STATICLIB) +jemalloc : $(MALLOC_STATICLIB) # skynet @@ -50,8 +51,8 @@ all : \ $(foreach v, $(CSERVICE), $(CSERVICE_PATH)/$(v).so) \ $(foreach v, $(LUA_CLIB), $(LUA_CLIB_PATH)/$(v).so) -$(SKYNET_BUILD_PATH)/skynet : $(foreach v, $(SKYNET_SRC), skynet-src/$(v)) $(LUA_LIB) $(JEMALLOC_STATICLIB) - $(CC) $(CFLAGS) -o $@ $^ -Iskynet-src -I$(JEMALLOC_INC) $(LDFLAGS) $(EXPORT) $(LIBS) +$(SKYNET_BUILD_PATH)/skynet : $(foreach v, $(SKYNET_SRC), skynet-src/$(v)) $(LUA_LIB) $(MALLOC_STATICLIB) + $(CC) $(CFLAGS) -o $@ $^ -Iskynet-src -I$(JEMALLOC_INC) $(LDFLAGS) $(EXPORT) $(LIBS) $(SKYNET_DEFINES) $(LUA_CLIB_PATH) : mkdir $(LUA_CLIB_PATH) diff --git a/platform.mk b/platform.mk index 20dba89c..9bbdb8a3 100644 --- a/platform.mk +++ b/platform.mk @@ -31,4 +31,7 @@ freebsd : PLAT = freebsd macosx linux : LIBS += -ldl macosx : SHARED := -fPIC -dynamiclib -Wl,-undefined,dynamic_lookup macosx : EXPORT := +macosx : MALLOC_STATICLIB := +macosx : SKYNET_DEFINES :=-DNOUSE_JEMALLOC linux freebsd : LIBS += -lrt +linux freebsd : MALLOC_STATICLIB = $(JEMALLOC_STATICLIB) diff --git a/skynet-src/malloc_hook.c b/skynet-src/malloc_hook.c index 19f6e3ad..2657f455 100644 --- a/skynet-src/malloc_hook.c +++ b/skynet-src/malloc_hook.c @@ -1,18 +1,40 @@ #include #include #include +#include + +#ifdef __APPLE__ +#include +#define malloc_usable_size(ptr) malloc_size(ptr) +#endif + +#ifdef __FreeBSD__ +#include +#endif + +#ifdef NOUSE_JEMALLOC + +#define je_malloc malloc +#define je_free free +#define je_calloc calloc +#define je_realloc realloc +#define je_malloc_usable_size malloc_usable_size + +#else -#include "malloc_hook.h" #include "jemalloc.h" +#endif + +#include "malloc_hook.h" #include "skynet.h" static size_t _used_memory = 0; static size_t _memory_block = 0; typedef struct _mem_data { - uint32_t handle; - ssize_t allocated; + uint32_t handle; + ssize_t allocated; } mem_data; #define SLOT_SIZE 0x10000 @@ -22,11 +44,11 @@ static mem_data mem_stats[SLOT_SIZE]; static ssize_t* get_allocated_field(uint32_t handle) { - int h = (int)(handle & (SLOT_SIZE - 1)); - mem_data *data = &mem_stats[h]; + int h = (int)(handle & (SLOT_SIZE - 1)); + mem_data *data = &mem_stats[h]; uint32_t old_handle = data->handle; ssize_t old_alloc = data->allocated; - if(old_handle == 0 || old_alloc <= 0) { + if(old_handle == 0 || old_alloc <= 0) { // data->allocated may less than zero, because it may not count at start. if(!__sync_bool_compare_and_swap(&data->handle, old_handle, handle)) { return 0; @@ -34,150 +56,176 @@ get_allocated_field(uint32_t handle) { if (old_alloc < 0) { __sync_bool_compare_and_swap(&data->allocated, old_alloc, 0); } - } - if(data->handle != handle) { - return 0; - } - return &data->allocated; + } + if(data->handle != handle) { + return 0; + } + return &data->allocated; } inline static void update_xmalloc_stat_alloc(uint32_t handle, size_t __n) { - __sync_add_and_fetch(&_used_memory, __n); - __sync_add_and_fetch(&_memory_block, 1); - ssize_t* allocated = get_allocated_field(handle); - if(allocated) { - __sync_add_and_fetch(allocated, __n); - } + __sync_add_and_fetch(&_used_memory, __n); + __sync_add_and_fetch(&_memory_block, 1); + ssize_t* allocated = get_allocated_field(handle); + if(allocated) { + __sync_add_and_fetch(allocated, __n); + } } inline static void update_xmalloc_stat_free(uint32_t handle, size_t __n) { - __sync_sub_and_fetch(&_used_memory, __n); - __sync_sub_and_fetch(&_memory_block, 1); - ssize_t* allocated = get_allocated_field(handle); - if(allocated) { - __sync_sub_and_fetch(allocated, __n); - } + __sync_sub_and_fetch(&_used_memory, __n); + __sync_sub_and_fetch(&_memory_block, 1); + ssize_t* allocated = get_allocated_field(handle); + if(allocated) { + __sync_sub_and_fetch(allocated, __n); + } } inline static void* fill_prefix(char* ptr) { - uint32_t handle = skynet_current_handle(); - size_t size = je_malloc_usable_size(ptr); - uint32_t *p = (uint32_t *)(ptr + size - sizeof(uint32_t)); - memcpy(p, &handle, sizeof(handle)); + uint32_t handle = skynet_current_handle(); + size_t size = je_malloc_usable_size(ptr); + uint32_t *p = (uint32_t *)(ptr + size - sizeof(uint32_t)); + memcpy(p, &handle, sizeof(handle)); update_xmalloc_stat_alloc(handle, size); - return ptr; + return ptr; } inline static void* clean_prefix(char* ptr) { - size_t size = je_malloc_usable_size(ptr); - uint32_t *p = (uint32_t *)(ptr + size - sizeof(uint32_t)); - uint32_t handle; - memcpy(&handle, p, sizeof(handle)); - update_xmalloc_stat_free(handle, size); - return ptr; + size_t size = je_malloc_usable_size(ptr); + uint32_t *p = (uint32_t *)(ptr + size - sizeof(uint32_t)); + uint32_t handle; + memcpy(&handle, p, sizeof(handle)); + update_xmalloc_stat_free(handle, size); + return ptr; } static void malloc_oom(size_t size) { - fprintf(stderr, "xmalloc: Out of memory trying to allocate %zu bytes\n", - size); - fflush(stderr); - abort(); + fprintf(stderr, "xmalloc: Out of memory trying to allocate %zu bytes\n", + size); + fflush(stderr); + abort(); } size_t malloc_used_memory(void) { - return _used_memory; + return _used_memory; } size_t malloc_memory_block(void) { - return _memory_block; + return _memory_block; } -void memory_info_dump(void) { - je_malloc_stats_print(0,0,0); +#ifdef NOUSE_JEMALLOC + +void +memory_info_dump(void) { + skynet_error(NULL, "No jemalloc"); } -size_t mallctl_int64(const char* name, size_t* newval) { - size_t v = 0; - size_t len = sizeof(v); - if(newval) { - je_mallctl(name, &v, &len, newval, sizeof(size_t)); - } else { - je_mallctl(name, &v, &len, NULL, 0); - } - // printf("name: %s, value: %zd\n", name, v); - return v; +size_t +mallctl_int64(const char* name, size_t* newval) { + skynet_error(NULL, "No jemalloc : mallctl_int64 %s.", name); + return 0; } -int mallctl_opt(const char* name, int* newval) { - int v = 0; - size_t len = sizeof(v); - if(newval) { - int ret = je_mallctl(name, &v, &len, newval, sizeof(int)); - if(ret == 0) { - printf("set new value(%d) for (%s) succeed\n", *newval, name); - } else { - printf("set new value(%d) for (%s) failed: error -> %d\n", *newval, name, ret); - } - } else { - je_mallctl(name, &v, &len, NULL, 0); - } - - return v; +int +mallctl_opt(const char* name, int* newval) { + skynet_error(NULL, "No jemalloc : mallctl_opt %s.", name); + return 0; } +#else + +void +memory_info_dump(void) { + je_malloc_stats_print(0,0,0); +} + +size_t +mallctl_int64(const char* name, size_t* newval) { + size_t v = 0; + size_t len = sizeof(v); + if(newval) { + je_mallctl(name, &v, &len, newval, sizeof(size_t)); + } else { + je_mallctl(name, &v, &len, NULL, 0); + } + // printf("name: %s, value: %zd\n", name, v); + return v; +} + +int +mallctl_opt(const char* name, int* newval) { + int v = 0; + size_t len = sizeof(v); + if(newval) { + int ret = je_mallctl(name, &v, &len, newval, sizeof(int)); + if(ret == 0) { + printf("set new value(%d) for (%s) succeed\n", *newval, name); + } else { + printf("set new value(%d) for (%s) failed: error -> %d\n", *newval, name, ret); + } + } else { + je_mallctl(name, &v, &len, NULL, 0); + } + + return v; +} + +#endif + void dump_c_mem() { - int i; - size_t total = 0; - printf("dump all service mem:\n"); - for(i=0; ihandle != 0 && data->allocated != 0) { - total += data->allocated; - printf("0x%x -> %zdkb\n", data->handle, data->allocated >> 10); - } - } - printf("+total: %zdkb\n",total >> 10); + int i; + size_t total = 0; + printf("dump all service mem:\n"); + for(i=0; ihandle != 0 && data->allocated != 0) { + total += data->allocated; + printf("0x%x -> %zdkb\n", data->handle, data->allocated >> 10); + } + } + printf("+total: %zdkb\n",total >> 10); } -// hook : malloc, realloc, memalign, free, calloc +// hook : malloc, realloc, free, calloc void * skynet_malloc(size_t size) { - void* ptr = je_malloc(size + PREFIX_SIZE); - if(!ptr) malloc_oom(size); - return fill_prefix(ptr); + void* ptr = je_malloc(size + PREFIX_SIZE); + if(!ptr) malloc_oom(size); + return fill_prefix(ptr); } void * skynet_realloc(void *ptr, size_t size) { - if (ptr == NULL) return skynet_malloc(size); + if (ptr == NULL) return skynet_malloc(size); - void* rawptr = clean_prefix(ptr); - void *newptr = je_realloc(rawptr, size+PREFIX_SIZE); - if(!newptr) malloc_oom(size); - return fill_prefix(newptr); + void* rawptr = clean_prefix(ptr); + void *newptr = je_realloc(rawptr, size+PREFIX_SIZE); + if(!newptr) malloc_oom(size); + return fill_prefix(newptr); } void skynet_free(void *ptr) { - if (ptr == NULL) return; - void* rawptr = clean_prefix(ptr); - je_free(rawptr); + if (ptr == NULL) return; + void* rawptr = clean_prefix(ptr); + je_free(rawptr); } void * skynet_calloc(size_t nmemb,size_t size) { - void* ptr = je_calloc(nmemb + ((PREFIX_SIZE+size-1)/size), size ); - if(!ptr) malloc_oom(size); - return fill_prefix(ptr); + void* ptr = je_calloc(nmemb + ((PREFIX_SIZE+size-1)/size), size ); + if(!ptr) malloc_oom(size); + return fill_prefix(ptr); } char * @@ -198,3 +246,8 @@ skynet_lalloc(void *ud, void *ptr, size_t osize, size_t nsize) { } } +void +malloc_inithook(void) { + memset(mem_stats, 0, sizeof(mem_stats)); +} +