Commit 0042a2d7 authored by antirez's avatar antirez
Browse files

jemalloc support backported in 2.4 using part of the Pieter Noordhuis and...

jemalloc support backported in 2.4 using part of the Pieter Noordhuis and Didier Spezia original implementations
parent 0811e89c
...@@ -12,6 +12,7 @@ clean: ...@@ -12,6 +12,7 @@ clean:
cd src && $(MAKE) $@ cd src && $(MAKE) $@
cd deps/hiredis && $(MAKE) $@ cd deps/hiredis && $(MAKE) $@
cd deps/linenoise && $(MAKE) $@ cd deps/linenoise && $(MAKE) $@
cd deps/jemalloc && $(MAKE) distclean
$(TARGETS): $(TARGETS):
cd src && $(MAKE) $@ cd src && $(MAKE) $@
......
...@@ -24,23 +24,6 @@ After building Redis is a good idea to test it, using: ...@@ -24,23 +24,6 @@ After building Redis is a good idea to test it, using:
% make test % make test
Buliding using tcmalloc
-----------------------
tcmalloc is a fast and space efficient implementation (for little objects)
of malloc(). Compiling Redis with it can improve performances and memeory
usage. You can read more about it here:
http://goog-perftools.sourceforge.net/doc/tcmalloc.html
In order to compile Redis with tcmalloc support install tcmalloc on your system
and then use:
% make USE_TCMALLOC=yes
Note that you can pass any other target to make, as long as you append
USE_TCMALLOC=yes at the end.
Running Redis Running Redis
------------- -------------
......
...@@ -5,35 +5,42 @@ ...@@ -5,35 +5,42 @@
release_hdr := $(shell sh -c './mkreleasehdr.sh') release_hdr := $(shell sh -c './mkreleasehdr.sh')
uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
OPTIMIZATION?=-O2 OPTIMIZATION?=-O2
ifeq ($(uname_S),Linux)
ifneq ($(FORCE_LIBC_MALLOC),yes)
USE_JEMALLOC=yes
endif
endif
ifeq ($(uname_S),SunOS) ifeq ($(uname_S),SunOS)
CFLAGS?= -std=c99 -pedantic $(OPTIMIZATION) -Wall -W -D__EXTENSIONS__ -D_XPG6 CFLAGS?=-std=c99 -pedantic $(OPTIMIZATION) -Wall -W -D__EXTENSIONS__ -D_XPG6
CCLINK?= -ldl -lnsl -lsocket -lm -lpthread CCLINK?=-ldl -lnsl -lsocket -lm -lpthread
DEBUG?= -g -ggdb DEBUG?=-g -ggdb
else else
CFLAGS?= -std=c99 -pedantic $(OPTIMIZATION) -Wall -W $(ARCH) $(PROF) CFLAGS?=-std=c99 -pedantic $(OPTIMIZATION) -Wall -W $(ARCH) $(PROF)
CCLINK?= -lm -pthread CCLINK?=-lm -pthread
DEBUG?= -g -rdynamic -ggdb DEBUG?=-g -rdynamic -ggdb
endif endif
ifeq ($(USE_TCMALLOC),yes) ifeq ($(USE_TCMALLOC),yes)
ALLOC_DEP=
ALLOC_LINK=-ltcmalloc ALLOC_LINK=-ltcmalloc
ALLOC_FLAGS=-DUSE_TCMALLOC ALLOC_FLAGS=-DUSE_TCMALLOC
endif endif
ifeq ($(USE_TCMALLOC_MINIMAL),yes) ifeq ($(USE_TCMALLOC_MINIMAL),yes)
ALLOC_DEP=
ALLOC_LINK=-ltcmalloc_minimal ALLOC_LINK=-ltcmalloc_minimal
ALLOC_FLAGS=-DUSE_TCMALLOC ALLOC_FLAGS=-DUSE_TCMALLOC
endif endif
ifeq ($(USE_JEMALLOC),yes) ifeq ($(USE_JEMALLOC),yes)
ALLOC_LINK=-ljemalloc ALLOC_DEP=../deps/jemalloc/lib/libjemalloc.a
ALLOC_FLAGS=-DUSE_JEMALLOC ALLOC_LINK=$(ALLOC_DEP)
ALLOC_FLAGS=-DUSE_JEMALLOC -I../deps/jemalloc/include
endif endif
CCLINK+= $(ALLOC_LINK) CCOPT= $(CFLAGS) $(ARCH) $(PROF)
CFLAGS+= $(ALLOC_FLAGS)
CCOPT= $(CFLAGS) $(CCLINK) $(ARCH) $(PROF)
PREFIX= /usr/local PREFIX= /usr/local
INSTALL_BIN= $(PREFIX)/bin INSTALL_BIN= $(PREFIX)/bin
...@@ -58,7 +65,7 @@ all: redis-benchmark redis-cli redis-check-dump redis-check-aof redis-server ...@@ -58,7 +65,7 @@ all: redis-benchmark redis-cli redis-check-dump redis-check-aof redis-server
# Deps (use make dep to generate this) # Deps (use make dep to generate this)
adlist.o: adlist.c adlist.h zmalloc.h adlist.o: adlist.c adlist.h zmalloc.h
ae.o: ae.c ae.h zmalloc.h config.h ae_kqueue.c ae.o: ae.c ae.h config.h zmalloc.h ae_epoll.c ae_kqueue.c ae_select.c
ae_epoll.o: ae_epoll.c ae_epoll.o: ae_epoll.c
ae_kqueue.o: ae_kqueue.c ae_kqueue.o: ae_kqueue.c
ae_select.o: ae_select.c ae_select.o: ae_select.c
...@@ -72,8 +79,8 @@ db.o: db.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \ ...@@ -72,8 +79,8 @@ db.o: db.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \
debug.o: debug.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \ debug.o: debug.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h sha1.h zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h sha1.h
dict.o: dict.c fmacros.h dict.h zmalloc.h dict.o: dict.c fmacros.h dict.h zmalloc.h
endian.o: endian.c
intset.o: intset.c intset.h zmalloc.h intset.o: intset.c intset.h zmalloc.h
endian.o: endian.c
lzf_c.o: lzf_c.c lzfP.h lzf_c.o: lzf_c.c lzfP.h
lzf_d.o: lzf_d.c lzfP.h lzf_d.o: lzf_d.c lzfP.h
multi.o: multi.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \ multi.o: multi.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \
...@@ -87,12 +94,12 @@ pubsub.o: pubsub.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \ ...@@ -87,12 +94,12 @@ pubsub.o: pubsub.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h
rdb.o: rdb.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \ rdb.o: rdb.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h lzf.h zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h lzf.h
redis-benchmark.o: redis-benchmark.c fmacros.h ae.h \ redis-benchmark.o: redis-benchmark.c fmacros.h ae.c ae.h ae_epoll.c \
../deps/hiredis/hiredis.h sds.h adlist.h zmalloc.h ae_kqueue.c ae_select.c config.h zmalloc.h ae_kqueue.c adlist.c adlist.h \
sds.c sds.h
redis-check-aof.o: redis-check-aof.c fmacros.h config.h redis-check-aof.o: redis-check-aof.c fmacros.h config.h
redis-check-dump.o: redis-check-dump.c lzf.h redis-check-dump.o: redis-check-dump.c lzf.h
redis-cli.o: redis-cli.c fmacros.h version.h ../deps/hiredis/hiredis.h \ redis-cli.o: redis-cli.c fmacros.h version.h help.h sds.c sds.h
sds.h zmalloc.h ../deps/linenoise/linenoise.h help.h
redis.o: redis.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \ redis.o: redis.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h
release.o: release.c release.h release.o: release.c release.h
...@@ -114,47 +121,61 @@ t_string.o: t_string.c redis.h fmacros.h config.h ae.h sds.h dict.h \ ...@@ -114,47 +121,61 @@ t_string.o: t_string.c redis.h fmacros.h config.h ae.h sds.h dict.h \
adlist.h zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h adlist.h zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h
t_zset.o: t_zset.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \ t_zset.o: t_zset.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h
util.o: util.c util.h util.o: util.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h
vm.o: vm.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \ vm.o: vm.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \
zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h zmalloc.h anet.h zipmap.h ziplist.h intset.h version.h
ziplist.o: ziplist.c zmalloc.h ziplist.h ziplist.o: ziplist.c zmalloc.h ziplist.h
zipmap.o: zipmap.c zmalloc.h endian.h zipmap.o: zipmap.c zmalloc.h
zmalloc.o: zmalloc.c config.h zmalloc.h zmalloc.o: zmalloc.c config.h zmalloc.h
.PHONY: dependencies
dependencies: dependencies:
cd ../deps/hiredis && $(MAKE) static ARCH="$(ARCH)" cd ../deps/hiredis && $(MAKE) static ARCH="$(ARCH)"
cd ../deps/linenoise && $(MAKE) ARCH="$(ARCH)" cd ../deps/linenoise && $(MAKE) ARCH="$(ARCH)"
redis-server: $(OBJ) ../deps/jemalloc/lib/libjemalloc.a:
$(CC) -o $(PRGNAME) $(CCOPT) $(DEBUG) $(OBJ) cd ../deps/jemalloc && ./configure --with-jemalloc-prefix=je_ --enable-cc-silence && $(MAKE) lib/libjemalloc.a
redis-benchmark: dependencies $(BENCHOBJ)
cd ../deps/hiredis && $(MAKE) static
$(CC) -o $(BENCHPRGNAME) $(CCOPT) $(DEBUG) $(BENCHOBJ) ../deps/hiredis/libhiredis.a
redis-benchmark.o: redis-benchmark.o:
$(CC) -c $(CFLAGS) -I../deps/hiredis $(DEBUG) $(COMPILE_TIME) $< $(CC) -c $(CFLAGS) -I../deps/hiredis $(DEBUG) $(COMPILE_TIME) $<
redis-cli: dependencies $(CLIOBJ) redis-benchmark: dependencies $(BENCHOBJ)
$(CC) -o $(CLIPRGNAME) $(CCOPT) $(DEBUG) $(CLIOBJ) ../deps/hiredis/libhiredis.a ../deps/linenoise/linenoise.o cd ../deps/hiredis && $(MAKE) static
$(CC) -o $(BENCHPRGNAME) $(CCOPT) $(DEBUG) $(BENCHOBJ) ../deps/hiredis/libhiredis.a $(CCLINK) $(ALLOC_LINK)
redis-cli.o: redis-cli.o:
$(CC) -c $(CFLAGS) -I../deps/hiredis -I../deps/linenoise $(DEBUG) $(COMPILE_TIME) $< $(CC) -c $(CFLAGS) -I../deps/hiredis -I../deps/linenoise $(DEBUG) $(COMPILE_TIME) $<
redis-cli: dependencies $(CLIOBJ)
$(CC) -o $(CLIPRGNAME) $(CCOPT) $(DEBUG) $(CLIOBJ) ../deps/hiredis/libhiredis.a ../deps/linenoise/linenoise.o $(CCLINK) $(ALLOC_LINK)
redis-check-dump.o:
$(CC) -c $(CFLAGS) $(DEBUG) $(COMPILE_TIME) $<
redis-check-dump: $(CHECKDUMPOBJ) redis-check-dump: $(CHECKDUMPOBJ)
$(CC) -o $(CHECKDUMPPRGNAME) $(CCOPT) $(DEBUG) $(CHECKDUMPOBJ) $(CC) -o $(CHECKDUMPPRGNAME) $(CCOPT) $(DEBUG) $(CHECKDUMPOBJ) $(CCLINK)
redis-check-aof.o:
$(CC) -c $(CFLAGS) $(DEBUG) $(COMPILE_TIME) $<
redis-check-aof: $(CHECKAOFOBJ) redis-check-aof: $(CHECKAOFOBJ)
$(CC) -o $(CHECKAOFPRGNAME) $(CCOPT) $(DEBUG) $(CHECKAOFOBJ) $(CC) -o $(CHECKAOFPRGNAME) $(CCOPT) $(DEBUG) $(CHECKAOFOBJ) $(CCLINK)
.c.o: redis-server: $(OBJ)
$(CC) -c $(CFLAGS) $(DEBUG) $(COMPILE_TIME) $< $(CC) -o $(PRGNAME) $(CCOPT) $(DEBUG) $(OBJ) $(CCLINK) $(ALLOC_LINK)
# Because the jemalloc.h header is generated as a part of the jemalloc build
# process, building it should complete before building any other object.
%.o: %.c $(ALLOC_DEP)
$(CC) -c $(CFLAGS) $(ALLOC_FLAGS) $(DEBUG) $(COMPILE_TIME) $<
clean: clean:
rm -rf $(PRGNAME) $(BENCHPRGNAME) $(CLIPRGNAME) $(CHECKDUMPPRGNAME) $(CHECKAOFPRGNAME) *.o *.gcda *.gcno *.gcov rm -rf $(PRGNAME) $(BENCHPRGNAME) $(CLIPRGNAME) $(CHECKDUMPPRGNAME) $(CHECKAOFPRGNAME) *.o *.gcda *.gcno *.gcov
dep: dep:
$(CC) -I../deps/hiredis -I../deps/linenoise -MM *.c $(CC) -MM *.c
test: redis-server test: redis-server
(cd ..; tclsh8.5 tests/test_helper.tcl --tags "${TAGS}" --file "${FILE}") (cd ..; tclsh8.5 tests/test_helper.tcl --tags "${TAGS}" --file "${FILE}")
......
...@@ -1232,7 +1232,7 @@ sds genRedisInfoString(void) { ...@@ -1232,7 +1232,7 @@ sds genRedisInfoString(void) {
server.stat_peak_memory, server.stat_peak_memory,
peak_hmem, peak_hmem,
zmalloc_get_fragmentation_ratio(), zmalloc_get_fragmentation_ratio(),
REDIS_MALLOC, ZMALLOC_LIB,
server.loading, server.loading,
server.appendonly, server.appendonly,
server.dirty, server.dirty,
......
...@@ -51,6 +51,11 @@ ...@@ -51,6 +51,11 @@
#define calloc(count,size) tc_calloc(count,size) #define calloc(count,size) tc_calloc(count,size)
#define realloc(ptr,size) tc_realloc(ptr,size) #define realloc(ptr,size) tc_realloc(ptr,size)
#define free(ptr) tc_free(ptr) #define free(ptr) tc_free(ptr)
#elif defined(USE_JEMALLOC)
#define malloc(size) je_malloc(size)
#define calloc(count,size) je_calloc(count,size)
#define realloc(ptr,size) je_realloc(ptr,size)
#define free(ptr) je_free(ptr)
#endif #endif
#define update_zmalloc_stat_alloc(__n,__size) do { \ #define update_zmalloc_stat_alloc(__n,__size) do { \
...@@ -98,7 +103,7 @@ void *zmalloc(size_t size) { ...@@ -98,7 +103,7 @@ void *zmalloc(size_t size) {
if (!ptr) zmalloc_oom(size); if (!ptr) zmalloc_oom(size);
#ifdef HAVE_MALLOC_SIZE #ifdef HAVE_MALLOC_SIZE
update_zmalloc_stat_alloc(redis_malloc_size(ptr),size); update_zmalloc_stat_alloc(zmalloc_size(ptr),size);
return ptr; return ptr;
#else #else
*((size_t*)ptr) = size; *((size_t*)ptr) = size;
...@@ -112,7 +117,7 @@ void *zcalloc(size_t size) { ...@@ -112,7 +117,7 @@ void *zcalloc(size_t size) {
if (!ptr) zmalloc_oom(size); if (!ptr) zmalloc_oom(size);
#ifdef HAVE_MALLOC_SIZE #ifdef HAVE_MALLOC_SIZE
update_zmalloc_stat_alloc(redis_malloc_size(ptr),size); update_zmalloc_stat_alloc(zmalloc_size(ptr),size);
return ptr; return ptr;
#else #else
*((size_t*)ptr) = size; *((size_t*)ptr) = size;
...@@ -130,12 +135,12 @@ void *zrealloc(void *ptr, size_t size) { ...@@ -130,12 +135,12 @@ void *zrealloc(void *ptr, size_t size) {
if (ptr == NULL) return zmalloc(size); if (ptr == NULL) return zmalloc(size);
#ifdef HAVE_MALLOC_SIZE #ifdef HAVE_MALLOC_SIZE
oldsize = redis_malloc_size(ptr); oldsize = zmalloc_size(ptr);
newptr = realloc(ptr,size); newptr = realloc(ptr,size);
if (!newptr) zmalloc_oom(size); if (!newptr) zmalloc_oom(size);
update_zmalloc_stat_free(oldsize); update_zmalloc_stat_free(oldsize);
update_zmalloc_stat_alloc(redis_malloc_size(newptr),size); update_zmalloc_stat_alloc(zmalloc_size(newptr),size);
return newptr; return newptr;
#else #else
realptr = (char*)ptr-PREFIX_SIZE; realptr = (char*)ptr-PREFIX_SIZE;
...@@ -158,7 +163,7 @@ void zfree(void *ptr) { ...@@ -158,7 +163,7 @@ void zfree(void *ptr) {
if (ptr == NULL) return; if (ptr == NULL) return;
#ifdef HAVE_MALLOC_SIZE #ifdef HAVE_MALLOC_SIZE
update_zmalloc_stat_free(redis_malloc_size(ptr)); update_zmalloc_stat_free(zmalloc_size(ptr));
free(ptr); free(ptr);
#else #else
realptr = (char*)ptr-PREFIX_SIZE; realptr = (char*)ptr-PREFIX_SIZE;
......
...@@ -28,8 +28,43 @@ ...@@ -28,8 +28,43 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef _ZMALLOC_H #ifndef __ZMALLOC_H
#define _ZMALLOC_H #define __ZMALLOC_H
/* Double expansion needed for stringification of macro values. */
#define __xstr(s) __str(s)
#define __str(s) #s
#if defined(USE_TCMALLOC)
#define ZMALLOC_LIB ("tcmalloc-" __xstr(TC_VERSION_MAJOR) "." __xstr(TC_VERSION_MINOR))
#include <google/tcmalloc.h>
#if TC_VERSION_MAJOR >= 1 && TC_VERSION_MINOR >= 6
#define HAVE_MALLOC_SIZE 1
#define zmalloc_size(p) tc_malloc_size(p)
#else
#error "Newer version of tcmalloc required"
#endif
#elif defined(USE_JEMALLOC)
#define ZMALLOC_LIB ("jemalloc-" __xstr(JEMALLOC_VERSION_MAJOR) "." __xstr(JEMALLOC_VERSION_MINOR) "." __xstr(JEMALLOC_VERSION_BUGFIX))
#define JEMALLOC_MANGLE
#include <jemalloc/jemalloc.h>
#if JEMALLOC_VERSION_MAJOR >= 2 && JEMALLOC_VERSION_MINOR >= 1
#define HAVE_MALLOC_SIZE 1
#define zmalloc_size(p) JEMALLOC_P(malloc_usable_size)(p)
#else
#error "Newer version of jemalloc required"
#endif
#elif defined(__APPLE__)
#include <malloc/malloc.h>
#define HAVE_MALLOC_SIZE 1
#define zmalloc_size(p) malloc_size(p)
#endif
#ifndef ZMALLOC_LIB
#define ZMALLOC_LIB "libc"
#endif
void *zmalloc(size_t size); void *zmalloc(size_t size);
void *zcalloc(size_t size); void *zcalloc(size_t size);
...@@ -44,4 +79,4 @@ size_t zmalloc_allocations_for_size(size_t size); ...@@ -44,4 +79,4 @@ size_t zmalloc_allocations_for_size(size_t size);
#define ZMALLOC_MAX_ALLOC_STAT 256 #define ZMALLOC_MAX_ALLOC_STAT 256
#endif /* _ZMALLOC_H */ #endif /* __ZMALLOC_H */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment