From 355f859134e6220cb35d7b3fa9ea19ea8d05c02a Mon Sep 17 00:00:00 2001 From: antirez Date: Sat, 4 Feb 2012 08:58:37 +0100 Subject: [PATCH] Use less memory when emitting the protocol, by using more shared objects for commonly emitted parts of the protocol. --- src/db.c | 5 +++-- src/networking.c | 12 ++++++++++++ src/pubsub.c | 12 ++++++------ src/redis.c | 9 +++++++-- src/redis.h | 9 ++++++--- 5 files changed, 34 insertions(+), 13 deletions(-) diff --git a/src/db.c b/src/db.c index fc366b07..a0775af9 100644 --- a/src/db.c +++ b/src/db.c @@ -488,9 +488,10 @@ long long getExpire(redisDb *db, robj *key) { void propagateExpire(redisDb *db, robj *key) { robj *argv[2]; - argv[0] = createStringObject("DEL",3); + argv[0] = shared.del; argv[1] = key; - incrRefCount(key); + incrRefCount(argv[0]); + incrRefCount(argv[1]); if (server.aof_state != REDIS_AOF_OFF) feedAppendOnlyFile(server.delCommand,db->id,argv,2); diff --git a/src/networking.c b/src/networking.c index 3938f3f6..30c93965 100644 --- a/src/networking.c +++ b/src/networking.c @@ -363,6 +363,18 @@ void addReplyDouble(redisClient *c, double d) { void addReplyLongLongWithPrefix(redisClient *c, long long ll, char prefix) { char buf[128]; int len; + + /* Things like $3\r\n or *2\r\n are emitted very often by the protocol + * so we have a few shared objects to use if the integer is small + * like it is most of the times. */ + if (prefix == '*' && ll < REDIS_SHARED_BULKHDR_LEN) { + addReply(c,shared.mbulkhdr[ll]); + return; + } else if (prefix == '$' && ll < REDIS_SHARED_BULKHDR_LEN) { + addReply(c,shared.bulkhdr[ll]); + return; + } + buf[0] = prefix; len = ll2string(buf+1,sizeof(buf)-1,ll); buf[len+1] = '\r'; diff --git a/src/pubsub.c b/src/pubsub.c index 27e6f9a5..984013bb 100644 --- a/src/pubsub.c +++ b/src/pubsub.c @@ -41,7 +41,7 @@ int pubsubSubscribeChannel(redisClient *c, robj *channel) { listAddNodeTail(clients,c); } /* Notify the client */ - addReply(c,shared.mbulk3); + addReply(c,shared.mbulkhdr[3]); addReply(c,shared.subscribebulk); addReplyBulk(c,channel); addReplyLongLong(c,dictSize(c->pubsub_channels)+listLength(c->pubsub_patterns)); @@ -77,7 +77,7 @@ int pubsubUnsubscribeChannel(redisClient *c, robj *channel, int notify) { } /* Notify the client */ if (notify) { - addReply(c,shared.mbulk3); + addReply(c,shared.mbulkhdr[3]); addReply(c,shared.unsubscribebulk); addReplyBulk(c,channel); addReplyLongLong(c,dictSize(c->pubsub_channels)+ @@ -103,7 +103,7 @@ int pubsubSubscribePattern(redisClient *c, robj *pattern) { listAddNodeTail(server.pubsub_patterns,pat); } /* Notify the client */ - addReply(c,shared.mbulk3); + addReply(c,shared.mbulkhdr[3]); addReply(c,shared.psubscribebulk); addReplyBulk(c,pattern); addReplyLongLong(c,dictSize(c->pubsub_channels)+listLength(c->pubsub_patterns)); @@ -128,7 +128,7 @@ int pubsubUnsubscribePattern(redisClient *c, robj *pattern, int notify) { } /* Notify the client */ if (notify) { - addReply(c,shared.mbulk3); + addReply(c,shared.mbulkhdr[3]); addReply(c,shared.punsubscribebulk); addReplyBulk(c,pattern); addReplyLongLong(c,dictSize(c->pubsub_channels)+ @@ -188,7 +188,7 @@ int pubsubPublishMessage(robj *channel, robj *message) { while ((ln = listNext(&li)) != NULL) { redisClient *c = ln->value; - addReply(c,shared.mbulk3); + addReply(c,shared.mbulkhdr[3]); addReply(c,shared.messagebulk); addReplyBulk(c,channel); addReplyBulk(c,message); @@ -206,7 +206,7 @@ int pubsubPublishMessage(robj *channel, robj *message) { sdslen(pat->pattern->ptr), (char*)channel->ptr, sdslen(channel->ptr),0)) { - addReply(pat->client,shared.mbulk4); + addReply(pat->client,shared.mbulkhdr[4]); addReply(pat->client,shared.pmessagebulk); addReplyBulk(pat->client,pat->pattern); addReplyBulk(pat->client,channel); diff --git a/src/redis.c b/src/redis.c index 765f58da..45ee07ca 100644 --- a/src/redis.c +++ b/src/redis.c @@ -851,12 +851,17 @@ void createSharedObjects(void) { shared.unsubscribebulk = createStringObject("$11\r\nunsubscribe\r\n",18); shared.psubscribebulk = createStringObject("$10\r\npsubscribe\r\n",17); shared.punsubscribebulk = createStringObject("$12\r\npunsubscribe\r\n",19); - shared.mbulk3 = createStringObject("*3\r\n",4); - shared.mbulk4 = createStringObject("*4\r\n",4); + shared.del = createStringObject("DEL",3); for (j = 0; j < REDIS_SHARED_INTEGERS; j++) { shared.integers[j] = createObject(REDIS_STRING,(void*)(long)j); shared.integers[j]->encoding = REDIS_ENCODING_INT; } + for (j = 0; j < REDIS_SHARED_BULKHDR_LEN; j++) { + shared.mbulkhdr[j] = createObject(REDIS_STRING, + sdscatprintf(sdsempty(),"*%d\r\n",j)); + shared.bulkhdr[j] = createObject(REDIS_STRING, + sdscatprintf(sdsempty(),"$%d\r\n",j)); + } } void initServerConfig() { diff --git a/src/redis.h b/src/redis.h index 8f19ad37..ad624111 100644 --- a/src/redis.h +++ b/src/redis.h @@ -46,6 +46,7 @@ #define REDIS_EXPIRELOOKUPS_PER_CRON 10 /* lookup 10 expires per loop */ #define REDIS_MAX_WRITE_PER_EVENT (1024*64) #define REDIS_SHARED_INTEGERS 10000 +#define REDIS_SHARED_BULKHDR_LEN 32 #define REDIS_MAX_LOGMSG_LEN 1024 /* Default maximum length of syslog messages */ #define REDIS_AOF_REWRITE_PERC 100 #define REDIS_AOF_REWRITE_MIN_SIZE (1024*1024) @@ -358,9 +359,11 @@ struct sharedObjectsStruct { *outofrangeerr, *noscripterr, *loadingerr, *slowscripterr, *plus, *select0, *select1, *select2, *select3, *select4, *select5, *select6, *select7, *select8, *select9, - *messagebulk, *pmessagebulk, *subscribebulk, *unsubscribebulk, *mbulk3, - *mbulk4, *psubscribebulk, *punsubscribebulk, - *integers[REDIS_SHARED_INTEGERS]; + *messagebulk, *pmessagebulk, *subscribebulk, *unsubscribebulk, + *psubscribebulk, *punsubscribebulk, *del, + *integers[REDIS_SHARED_INTEGERS], + *mbulkhdr[REDIS_SHARED_BULKHDR_LEN], /* "*\r\n" */ + *bulkhdr[REDIS_SHARED_BULKHDR_LEN]; /* "$\r\n" */ }; /* ZSETs use a specialized version of Skiplists */ -- 2.45.2