diff --git a/.gitignore b/.gitignore index 262faef3..1f480bd4 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ src/redis.conf deps/lua/src/lua deps/lua/src/luac deps/lua/src/liblua.a +.make-* diff --git a/README b/README index e3054887..3920b534 100644 --- a/README +++ b/README @@ -26,18 +26,19 @@ NOTE: if after building Redis with a 32 bit target you need to rebuild it Allocator --------- -By default Redis compiles and links against jemalloc under Linux, since -glibc malloc() has memory fragmentation problems. +Selecting a non-default memory allocator when building Redis is done by setting +the `MALLOC` environment variable. Redis is compiled and linked against libc +malloc by default, with the exception of jemalloc being the default on Linux +systems. This default was picked because jemalloc has proven to have fewer +fragmentation problems than libc malloc. -To force a libc malloc() build use: +To force compiling against libc malloc, use: - % make FORCE_LIBC_MALLOC=yes + % make MALLOC=libc -In all the other non Linux systems the libc malloc() is used by default. +To compile against jemalloc on Mac OS X systems, use: -On Mac OS X you can force a jemalloc based build using the following: - - % make USE_JEMALLOC=yes + % make MALLOC=jemalloc Verbose build ------------- diff --git a/deps/Makefile b/deps/Makefile new file mode 100644 index 00000000..b881c814 --- /dev/null +++ b/deps/Makefile @@ -0,0 +1,59 @@ +# Redis dependency Makefile + +UNAME_S:=$(shell sh -c 'uname -s 2> /dev/null || echo not') + +LUA_CFLAGS=-O2 -Wall $(ARCH) +ifeq ($(UNAME_S),SunOS) + # Make isinf() available + LUA_CFLAGS+= -D__C99FEATURES__=1 +endif + +JEMALLOC_CFLAGS= +ifeq ($(ARCH),-m32) + JEMALLOC_CFLAGS+=CFLAGS="-std=gnu99 -Wall -pipe -g3 -fvisibility=hidden -O3 -funroll-loops -m32" +endif + +CCCOLOR="\033[34m" +LINKCOLOR="\033[34;1m" +SRCCOLOR="\033[33m" +BINCOLOR="\033[37;1m" +MAKECOLOR="\033[32;1m" +ENDCOLOR="\033[0m" + +default: + @echo "Explicit target required" + +# Clean everything when ARCH is different +ifneq ($(shell sh -c '[ -f .make-arch ] && cat .make-arch'), $(ARCH)) +.make-arch: distclean +else +.make-arch: +endif + +.make-arch: + -(echo $(ARCH) > .make-arch) + +distclean: + -(cd hiredis && $(MAKE) clean) > /dev/null || true + -(cd linenoise && $(MAKE) clean) > /dev/null || true + -(cd lua && $(MAKE) clean) > /dev/null || true + -(cd jemalloc && [ -f Makefile ] && $(MAKE) distclean) > /dev/null || true + -(rm -f .make-arch) + +hiredis: .make-arch + @printf '%b %b\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)hiredis$(ENDCOLOR) + cd hiredis && $(MAKE) static ARCH="$(ARCH)" + +linenoise: .make-arch + @printf '%b %b\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)linenoise$(ENDCOLOR) + cd linenoise && $(MAKE) ARCH="$(ARCH)" + +lua: .make-arch + @printf '%b %b\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)lua$(ENDCOLOR) + cd lua && $(MAKE) CFLAGS="$(LUA_CFLAGS)" MYLDFLAGS="$(ARCH)" ansi + +jemalloc: .make-arch + @printf '%b %b\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)jemalloc$(ENDCOLOR) + cd jemalloc && ./configure $(JEMALLOC_CFLAGS) --with-jemalloc-prefix=je_ --enable-cc-silence && $(MAKE) lib/libjemalloc.a + +.PHONY: default conditional_clean hiredis linenoise lua jemalloc diff --git a/src/Makefile b/src/Makefile index 6cb5f062..bedc5026 100644 --- a/src/Makefile +++ b/src/Makefile @@ -5,18 +5,9 @@ release_hdr := $(shell sh -c './mkreleasehdr.sh') uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') OPTIMIZATION?=-O2 - -LUA_CFLAGS=-O2 -Wall - -ifeq ($(uname_S),Linux) - ifneq ($(FORCE_LIBC_MALLOC),yes) - USE_JEMALLOC=yes - endif -endif +DEPENDENCY_TARGETS=hiredis linenoise lua ifeq ($(uname_S),SunOS) - # make isinf() available - LUA_CFLAGS+=-D__C99FEATURES__=1 CFLAGS?=-std=c99 -pedantic $(OPTIMIZATION) -Wall -W -D__EXTENSIONS__ -D_XPG6 CCLINK?=-ldl -lnsl -lsocket -lm -lpthread DEBUG?=-g -ggdb @@ -26,28 +17,44 @@ else DEBUG?=-g -rdynamic -ggdb endif +# Default allocator +ifeq ($(uname_S),Linux) + MALLOC?=jemalloc +else + MALLOC?=libc +endif + +# Backwards compatibility for selecting an allocator ifeq ($(USE_TCMALLOC),yes) - ALLOD_DEPS= + MALLOC=tcmalloc +endif + +ifeq ($(USE_TCMALLOC_MINIMAL),yes) + MALLOC=tcmalloc_minimal +endif + +ifeq ($(USE_JEMALLOC),yes) + MALLOC=jemalloc +endif + +ifeq ($(MALLOC),tcmalloc) ALLOC_LINK=-ltcmalloc ALLOC_FLAGS=-DUSE_TCMALLOC endif -ifeq ($(USE_TCMALLOC_MINIMAL),yes) - ALLOD_DEPS= +ifeq ($(MALLOC),tcmalloc_minimal) ALLOC_LINK=-ltcmalloc_minimal ALLOC_FLAGS=-DUSE_TCMALLOC endif -ifeq ($(USE_JEMALLOC),yes) - ALLOC_DEP=../deps/jemalloc/lib/libjemalloc.a - ALLOC_LINK=$(ALLOC_DEP) -ldl +ifeq ($(MALLOC),jemalloc) + ALLOC_LINK=../deps/jemalloc/lib/libjemalloc.a -ldl ALLOC_FLAGS=-DUSE_JEMALLOC -I../deps/jemalloc/include + DEPENDENCY_TARGETS+= jemalloc endif CCLINK+= $(ALLOC_LINK) CFLAGS+= $(ALLOC_FLAGS) -LUA_CFLAGS+= $(ARCH) - CCOPT= $(CFLAGS) $(ARCH) $(PROF) PREFIX= /usr/local @@ -160,52 +167,65 @@ ziplist.o: ziplist.c zmalloc.h util.h ziplist.h endian.h zipmap.o: zipmap.c zmalloc.h endian.h zmalloc.o: zmalloc.c config.h zmalloc.h -.PHONY: dependencies +# Clean local objects when ARCH is different +ifneq ($(shell sh -c '[ -f .make-arch ] && cat .make-arch'), $(ARCH)) +.make-arch: clean +else +.make-arch: +endif -dependencies: - @printf '%b %b\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)hiredis$(ENDCOLOR) - @cd ../deps/hiredis && $(MAKE) static ARCH="$(ARCH)" - @printf '%b %b\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)linenoise$(ENDCOLOR) - @cd ../deps/linenoise && $(MAKE) ARCH="$(ARCH)" - @echo $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)Lua ansi$(ENDCOLOR) - @cd ../deps/lua && $(MAKE) CFLAGS="$(LUA_CFLAGS)" MYLDFLAGS="$(ARCH)" ansi +.make-arch: + -(cd ../deps && make $(DEPENDENCY_TARGETS) ARCH="$(ARCH)") + -(echo $(ARCH) > .make-arch) -../deps/jemalloc/lib/libjemalloc.a: - cd ../deps/jemalloc && ./configure $(JEMALLOC_CFLAGS) --with-jemalloc-prefix=je_ --enable-cc-silence && $(MAKE) lib/libjemalloc.a +# Clean local objects when allocator changes +ifneq ($(shell sh -c '[ -f .make-malloc ] && cat .make-malloc'), $(MALLOC)) +.make-malloc: clean +else +.make-malloc: +endif -redis-server: dependencies $(OBJ) - $(QUIET_LINK)$(CC) -o $(PRGNAME) $(CCOPT) $(DEBUG) $(OBJ) $(CCLINK) $(ALLOC_LINK) ../deps/lua/src/liblua.a +.make-malloc: + -(echo $(MALLOC) > .make-malloc) -redis-benchmark: dependencies $(BENCHOBJ) - @cd ../deps/hiredis && $(MAKE) static - $(QUIET_LINK)$(CC) -o $(BENCHPRGNAME) $(CCOPT) $(DEBUG) $(BENCHOBJ) ../deps/hiredis/libhiredis.a $(CCLINK) $(ALLOC_LINK) +# Union of prerequisites +.prerequisites: .make-arch .make-malloc -redis-benchmark.o: +redis-server: .prerequisites $(OBJ) + $(QUIET_LINK)$(CC) -o $(PRGNAME) $(CCOPT) $(DEBUG) $(OBJ) ../deps/lua/src/liblua.a $(CCLINK) + +redis-benchmark: .prerequisites $(BENCHOBJ) + $(QUIET_LINK)$(CC) -o $(BENCHPRGNAME) $(CCOPT) $(DEBUG) $(BENCHOBJ) ../deps/hiredis/libhiredis.a $(CCLINK) + +redis-benchmark.o: redis-benchmark.c .prerequisites $(QUIET_CC)$(CC) -c $(CFLAGS) -I../deps/hiredis $(DEBUG) $(COMPILE_TIME) $< -redis-cli: dependencies $(CLIOBJ) - $(QUIET_LINK)$(CC) -o $(CLIPRGNAME) $(CCOPT) $(DEBUG) $(CLIOBJ) ../deps/hiredis/libhiredis.a ../deps/linenoise/linenoise.o $(CCLINK) $(ALLOC_LINK) +redis-cli: .prerequisites $(CLIOBJ) + $(QUIET_LINK)$(CC) -o $(CLIPRGNAME) $(CCOPT) $(DEBUG) $(CLIOBJ) ../deps/hiredis/libhiredis.a ../deps/linenoise/linenoise.o $(CCLINK) -redis-cli.o: +redis-cli.o: redis-cli.c .prerequisites $(QUIET_CC)$(CC) -c $(CFLAGS) -I../deps/hiredis -I../deps/linenoise $(DEBUG) $(COMPILE_TIME) $< -redis-check-dump: $(CHECKDUMPOBJ) - $(QUIET_LINK)$(CC) -o $(CHECKDUMPPRGNAME) $(CCOPT) $(DEBUG) $(CHECKDUMPOBJ) $(CCLINK) $(ALLOC_LINK) +redis-check-dump: .prerequisites $(CHECKDUMPOBJ) + $(QUIET_LINK)$(CC) -o $(CHECKDUMPPRGNAME) $(CCOPT) $(DEBUG) $(CHECKDUMPOBJ) $(CCLINK) -redis-check-aof: $(CHECKAOFOBJ) - $(QUIET_LINK)$(CC) -o $(CHECKAOFPRGNAME) $(CCOPT) $(DEBUG) $(CHECKAOFOBJ) $(CCLINK) $(ALLOC_LINK) +redis-check-aof: .prerequisites $(CHECKAOFOBJ) + $(QUIET_LINK)$(CC) -o $(CHECKAOFPRGNAME) $(CCOPT) $(DEBUG) $(CHECKAOFOBJ) $(CCLINK) # 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) +# process, building it should complete before building any other object. Instead of +# depending on a single artifact, simply build all dependencies first. +%.o: %.c .prerequisites $(QUIET_CC)$(CC) -c $(CFLAGS) $(DEBUG) $(COMPILE_TIME) -I../deps/lua/src $< +.PHONY: all clean distclean + clean: rm -rf $(PRGNAME) $(BENCHPRGNAME) $(CLIPRGNAME) $(CHECKDUMPPRGNAME) $(CHECKAOFPRGNAME) *.o *.gcda *.gcno *.gcov - cd ../deps/hiredis && $(MAKE) $@ - cd ../deps/linenoise && $(MAKE) $@ - cd ../deps/lua && $(MAKE) $@ - -(cd ../deps/jemalloc && $(MAKE) distclean) + +distclean: clean + -(cd ../deps && $(MAKE) distclean) + -(rm -f .make-arch .make-malloc) dep: $(CC) -MM *.c -I ../deps/hiredis -I ../deps/linenoise