From a4961a9a1dae02551041a10bfe6303cde0a4e76d Mon Sep 17 00:00:00 2001 From: antirez Date: Fri, 4 Apr 2014 16:36:44 +0200 Subject: [PATCH] No hard limits to LZF compression max size. --- src/object.c | 28 ++++++++++++++++++++-------- src/redis.c | 1 + src/redis.h | 2 ++ 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/object.c b/src/object.c index 0ae60c3aa..a97649d93 100644 --- a/src/object.c +++ b/src/object.c @@ -338,8 +338,7 @@ int isObjectRepresentableAsLongLong(robj *o, long long *llval) { } /* Try to encode a string object in order to save space. */ -#define REDIS_ENCODING_LZF_MAX_SIZE (1024*64) -#define REDIS_ENCODING_LZF_MAX_COMPR_SIZE (1024*32) +#define LZF_COMPR_STATIC_BUF (1024*32) robj *tryObjectEncoding(robj *o) { long value; sds s = o->ptr; @@ -398,18 +397,23 @@ robj *tryObjectEncoding(robj *o) { return emb; } - /* Try LZF compression for objects up to REDIS_ENCODING_LZF_MAX_SIZE + /* Try LZF compression for objects up to server.mem_compression_max_size * and greater than REDIS_ENCODING_EMBSTR_SIZE_LIMIT. */ - if (server.mem_compression && len <= REDIS_ENCODING_LZF_MAX_SIZE) { + if (server.mem_compression && len <= server.mem_compression_max_size) { /* Allocate four more bytes in our buffer since we need to store * the size of the compressed string as header. */ - unsigned char compr[4+REDIS_ENCODING_LZF_MAX_COMPR_SIZE]; + unsigned char compr_static[LZF_COMPR_STATIC_BUF]; + unsigned char *compr = compr_static; size_t comprlen, outlen; /* Save want to save at least 25% of memory for this to make sense. */ outlen = len-4-(len/4); - if (outlen > REDIS_ENCODING_LZF_MAX_SIZE) - outlen = REDIS_ENCODING_LZF_MAX_SIZE; + + /* Use an heap allocated buffer if the output is too big for our + * static buffer. We use the trick to directly allocating an empty + * SDS string so we can use it directly to create the object later. */ + if (outlen+4 > LZF_COMPR_STATIC_BUF) + compr = (unsigned char*) sdsnewlen(NULL,outlen+4); comprlen = lzf_compress(s,len,compr+4,outlen); if (comprlen != 0) { /* Object successfully compressed within the required space. */ @@ -419,9 +423,17 @@ robj *tryObjectEncoding(robj *o) { compr[3] = (len >> 24) & 0xff; if (o->encoding == REDIS_ENCODING_RAW) sdsfree(o->ptr); o->encoding = REDIS_ENCODING_LZF; - o->ptr = sdsnewlen(compr,comprlen+4); + if (compr == compr_static) { + /* When compressing to the static buffer we have to + * generate the SDS string here. */ + o->ptr = sdsnewlen(compr,comprlen+4); + } else { + /* Already an SDS, use it. */ + o->ptr = compr; + } return o; } + if (compr != compr_static) sdsfree((char*)compr); } /* We can't encode the object... diff --git a/src/redis.c b/src/redis.c index 24cf5e2ea..5943c26f3 100644 --- a/src/redis.c +++ b/src/redis.c @@ -1398,6 +1398,7 @@ void initServerConfig() { server.requirepass = NULL; server.rdb_compression = REDIS_DEFAULT_RDB_COMPRESSION; server.mem_compression = REDIS_DEFAULT_MEM_COMPRESSION; + server.mem_compression_max_size = REDIS_DEFAULT_MEM_COMPRESSION_MAX_SIZE; server.rdb_checksum = REDIS_DEFAULT_RDB_CHECKSUM; server.stop_writes_on_bgsave_err = REDIS_DEFAULT_STOP_WRITES_ON_BGSAVE_ERROR; server.activerehashing = REDIS_DEFAULT_ACTIVE_REHASHING; diff --git a/src/redis.h b/src/redis.h index 37b946c2d..a5b7c3c0b 100644 --- a/src/redis.h +++ b/src/redis.h @@ -108,6 +108,7 @@ #define REDIS_DEFAULT_STOP_WRITES_ON_BGSAVE_ERROR 1 #define REDIS_DEFAULT_RDB_COMPRESSION 1 #define REDIS_DEFAULT_MEM_COMPRESSION 0 +#define REDIS_DEFAULT_MEM_COMPRESSION_MAX_SIZE (1024*64) #define REDIS_DEFAULT_RDB_CHECKSUM 1 #define REDIS_DEFAULT_RDB_FILENAME "dump.rdb" #define REDIS_DEFAULT_SLAVE_SERVE_STALE_DATA 1 @@ -812,6 +813,7 @@ struct redisServer { size_t zset_max_ziplist_entries; size_t zset_max_ziplist_value; int mem_compression; /* In memory LZF compression. */ + size_t mem_compression_max_size; /* Try to compress up to this size. */ time_t unixtime; /* Unix time sampled every cron cycle. */ long long mstime; /* Like unixtime but in milliseconds. */ /* Pubsub */ -- GitLab