Merge branch 'vm-speedup'

This commit is contained in:
antirez 2010-05-12 11:51:01 +02:00
commit abce5627d7
3 changed files with 92 additions and 24 deletions

100
redis.c
View File

@ -622,6 +622,7 @@ static int pubsubUnsubscribeAllPatterns(redisClient *c, int notify);
static void freePubsubPattern(void *p); static void freePubsubPattern(void *p);
static int listMatchPubsubPattern(void *a, void *b); static int listMatchPubsubPattern(void *a, void *b);
static int compareStringObjects(robj *a, robj *b); static int compareStringObjects(robj *a, robj *b);
static int equalStringObjects(robj *a, robj *b);
static void usage(); static void usage();
static int rewriteAppendOnlyFileBackground(void); static int rewriteAppendOnlyFileBackground(void);
static int vmSwapObjectBlocking(robj *key, robj *val); static int vmSwapObjectBlocking(robj *key, robj *val);
@ -1022,6 +1023,30 @@ static long long memtoll(const char *p, int *err) {
return val*mul; return val*mul;
} }
/* Convert a long long into a string. Returns the number of
* characters needed to represent the number, that can be shorter if passed
* buffer length is not enough to store the whole number. */
static int ll2string(char *s, size_t len, long long value) {
char buf[32], *p;
unsigned long long v;
size_t l;
if (len == 0) return 0;
v = (value < 0) ? -value : value;
p = buf+31; /* point to the last character */
do {
*p-- = '0'+(v%10);
v /= 10;
} while(v);
if (value < 0) *p-- = '-';
p++;
l = 32-(p-buf);
if (l+1 > len) l = len-1; /* Make sure it fits, including the nul term */
memcpy(s,p,l);
s[l] = '\0';
return l;
}
static void redisLog(int level, const char *fmt, ...) { static void redisLog(int level, const char *fmt, ...) {
va_list ap; va_list ap;
FILE *fp; FILE *fp;
@ -1104,8 +1129,8 @@ static int dictEncObjKeyCompare(void *privdata, const void *key1,
int cmp; int cmp;
if (o1->encoding == REDIS_ENCODING_INT && if (o1->encoding == REDIS_ENCODING_INT &&
o2->encoding == REDIS_ENCODING_INT && o2->encoding == REDIS_ENCODING_INT)
o1->ptr == o2->ptr) return 1; return o1->ptr == o2->ptr;
o1 = getDecodedObject(o1); o1 = getDecodedObject(o1);
o2 = getDecodedObject(o2); o2 = getDecodedObject(o2);
@ -1125,7 +1150,7 @@ static unsigned int dictEncObjHash(const void *key) {
char buf[32]; char buf[32];
int len; int len;
len = snprintf(buf,32,"%ld",(long)o->ptr); len = ll2string(buf,32,(long)o->ptr);
return dictGenHashFunction((unsigned char*)buf, len); return dictGenHashFunction((unsigned char*)buf, len);
} else { } else {
unsigned int hash; unsigned int hash;
@ -2656,7 +2681,7 @@ static void *dupClientReplyValue(void *o) {
} }
static int listMatchObjects(void *a, void *b) { static int listMatchObjects(void *a, void *b) {
return compareStringObjects(a,b) == 0; return equalStringObjects(a,b);
} }
static redisClient *createClient(int fd) { static redisClient *createClient(int fd) {
@ -2896,7 +2921,7 @@ static robj *createStringObjectFromLongLong(long long value) {
o->encoding = REDIS_ENCODING_INT; o->encoding = REDIS_ENCODING_INT;
o->ptr = (void*)((long)value); o->ptr = (void*)((long)value);
} else { } else {
o->ptr = sdscatprintf(sdsempty(),"%lld",value); o = createObject(REDIS_STRING,sdsfromlonglong(value));
} }
} }
return o; return o;
@ -3111,7 +3136,7 @@ static int isStringRepresentableAsLong(sds s, long *longval) {
value = strtol(s, &endptr, 10); value = strtol(s, &endptr, 10);
if (endptr[0] != '\0') return REDIS_ERR; if (endptr[0] != '\0') return REDIS_ERR;
slen = snprintf(buf,32,"%ld",value); slen = ll2string(buf,32,value);
/* If the number converted back into a string is not identical /* If the number converted back into a string is not identical
* then it's not possible to encode the string as integer */ * then it's not possible to encode the string as integer */
@ -3164,7 +3189,7 @@ static robj *getDecodedObject(robj *o) {
if (o->type == REDIS_STRING && o->encoding == REDIS_ENCODING_INT) { if (o->type == REDIS_STRING && o->encoding == REDIS_ENCODING_INT) {
char buf[32]; char buf[32];
snprintf(buf,32,"%ld",(long)o->ptr); ll2string(buf,32,(long)o->ptr);
dec = createStringObject(buf,strlen(buf)); dec = createStringObject(buf,strlen(buf));
return dec; return dec;
} else { } else {
@ -3174,7 +3199,7 @@ static robj *getDecodedObject(robj *o) {
/* Compare two string objects via strcmp() or alike. /* Compare two string objects via strcmp() or alike.
* Note that the objects may be integer-encoded. In such a case we * Note that the objects may be integer-encoded. In such a case we
* use snprintf() to get a string representation of the numbers on the stack * use ll2string() to get a string representation of the numbers on the stack
* and compare the strings, it's much faster than calling getDecodedObject(). * and compare the strings, it's much faster than calling getDecodedObject().
* *
* Important note: if objects are not integer encoded, but binary-safe strings, * Important note: if objects are not integer encoded, but binary-safe strings,
@ -3187,14 +3212,14 @@ static int compareStringObjects(robj *a, robj *b) {
if (a == b) return 0; if (a == b) return 0;
if (a->encoding != REDIS_ENCODING_RAW) { if (a->encoding != REDIS_ENCODING_RAW) {
snprintf(bufa,sizeof(bufa),"%ld",(long) a->ptr); ll2string(bufa,sizeof(bufa),(long) a->ptr);
astr = bufa; astr = bufa;
bothsds = 0; bothsds = 0;
} else { } else {
astr = a->ptr; astr = a->ptr;
} }
if (b->encoding != REDIS_ENCODING_RAW) { if (b->encoding != REDIS_ENCODING_RAW) {
snprintf(bufb,sizeof(bufb),"%ld",(long) b->ptr); ll2string(bufb,sizeof(bufb),(long) b->ptr);
bstr = bufb; bstr = bufb;
bothsds = 0; bothsds = 0;
} else { } else {
@ -3203,6 +3228,18 @@ static int compareStringObjects(robj *a, robj *b) {
return bothsds ? sdscmp(astr,bstr) : strcmp(astr,bstr); return bothsds ? sdscmp(astr,bstr) : strcmp(astr,bstr);
} }
/* Equal string objects return 1 if the two objects are the same from the
* point of view of a string comparison, otherwise 0 is returned. Note that
* this function is faster then checking for (compareStringObject(a,b) == 0)
* because it can perform some more optimization. */
static int equalStringObjects(robj *a, robj *b) {
if (a->encoding != REDIS_ENCODING_RAW && b->encoding != REDIS_ENCODING_RAW){
return a->ptr == b->ptr;
} else {
return compareStringObjects(a,b) == 0;
}
}
static size_t stringObjectLen(robj *o) { static size_t stringObjectLen(robj *o) {
redisAssert(o->type == REDIS_STRING); redisAssert(o->type == REDIS_STRING);
if (o->encoding == REDIS_ENCODING_RAW) { if (o->encoding == REDIS_ENCODING_RAW) {
@ -3210,7 +3247,7 @@ static size_t stringObjectLen(robj *o) {
} else { } else {
char buf[32]; char buf[32];
return snprintf(buf,32,"%ld",(long)o->ptr); return ll2string(buf,32,(long)o->ptr);
} }
} }
@ -3351,7 +3388,7 @@ static int rdbTryIntegerEncoding(char *s, size_t len, unsigned char *enc) {
/* Check if it's possible to encode this value as a number */ /* Check if it's possible to encode this value as a number */
value = strtoll(s, &endptr, 10); value = strtoll(s, &endptr, 10);
if (endptr[0] != '\0') return 0; if (endptr[0] != '\0') return 0;
snprintf(buf,32,"%lld",value); ll2string(buf,32,value);
/* If the number converted back into a string is not identical /* If the number converted back into a string is not identical
* then it's not possible to encode the string as integer */ * then it's not possible to encode the string as integer */
@ -3760,7 +3797,11 @@ static uint32_t rdbLoadLen(FILE *fp, int *isencoded) {
} }
} }
static robj *rdbLoadIntegerObject(FILE *fp, int enctype) { /* Load an integer-encoded object from file 'fp', with the specified
* encoding type 'enctype'. If encode is true the function may return
* an integer-encoded object as reply, otherwise the returned object
* will always be encoded as a raw string. */
static robj *rdbLoadIntegerObject(FILE *fp, int enctype, int encode) {
unsigned char enc[4]; unsigned char enc[4];
long long val; long long val;
@ -3781,7 +3822,10 @@ static robj *rdbLoadIntegerObject(FILE *fp, int enctype) {
val = 0; /* anti-warning */ val = 0; /* anti-warning */
redisPanic("Unknown RDB integer encoding type"); redisPanic("Unknown RDB integer encoding type");
} }
return createObject(REDIS_STRING,sdscatprintf(sdsempty(),"%lld",val)); if (encode)
return createStringObjectFromLongLong(val);
else
return createObject(REDIS_STRING,sdsfromlonglong(val));
} }
static robj *rdbLoadLzfStringObject(FILE*fp) { static robj *rdbLoadLzfStringObject(FILE*fp) {
@ -3803,7 +3847,7 @@ err:
return NULL; return NULL;
} }
static robj *rdbLoadStringObject(FILE*fp) { static robj *rdbGenericLoadStringObject(FILE*fp, int encode) {
int isencoded; int isencoded;
uint32_t len; uint32_t len;
sds val; sds val;
@ -3814,7 +3858,7 @@ static robj *rdbLoadStringObject(FILE*fp) {
case REDIS_RDB_ENC_INT8: case REDIS_RDB_ENC_INT8:
case REDIS_RDB_ENC_INT16: case REDIS_RDB_ENC_INT16:
case REDIS_RDB_ENC_INT32: case REDIS_RDB_ENC_INT32:
return rdbLoadIntegerObject(fp,len); return rdbLoadIntegerObject(fp,len,encode);
case REDIS_RDB_ENC_LZF: case REDIS_RDB_ENC_LZF:
return rdbLoadLzfStringObject(fp); return rdbLoadLzfStringObject(fp);
default: default:
@ -3831,6 +3875,14 @@ static robj *rdbLoadStringObject(FILE*fp) {
return createObject(REDIS_STRING,val); return createObject(REDIS_STRING,val);
} }
static robj *rdbLoadStringObject(FILE *fp) {
return rdbGenericLoadStringObject(fp,0);
}
static robj *rdbLoadEncodedStringObject(FILE *fp) {
return rdbGenericLoadStringObject(fp,1);
}
/* For information about double serialization check rdbSaveDoubleValue() */ /* For information about double serialization check rdbSaveDoubleValue() */
static int rdbLoadDoubleValue(FILE *fp, double *val) { static int rdbLoadDoubleValue(FILE *fp, double *val) {
char buf[128]; char buf[128];
@ -3857,7 +3909,7 @@ static robj *rdbLoadObject(int type, FILE *fp) {
redisLog(REDIS_DEBUG,"LOADING OBJECT %d (at %d)\n",type,ftell(fp)); redisLog(REDIS_DEBUG,"LOADING OBJECT %d (at %d)\n",type,ftell(fp));
if (type == REDIS_STRING) { if (type == REDIS_STRING) {
/* Read string value */ /* Read string value */
if ((o = rdbLoadStringObject(fp)) == NULL) return NULL; if ((o = rdbLoadEncodedStringObject(fp)) == NULL) return NULL;
o = tryObjectEncoding(o); o = tryObjectEncoding(o);
} else if (type == REDIS_LIST || type == REDIS_SET) { } else if (type == REDIS_LIST || type == REDIS_SET) {
/* Read list/set value */ /* Read list/set value */
@ -3873,7 +3925,7 @@ static robj *rdbLoadObject(int type, FILE *fp) {
while(listlen--) { while(listlen--) {
robj *ele; robj *ele;
if ((ele = rdbLoadStringObject(fp)) == NULL) return NULL; if ((ele = rdbLoadEncodedStringObject(fp)) == NULL) return NULL;
ele = tryObjectEncoding(ele); ele = tryObjectEncoding(ele);
if (type == REDIS_LIST) { if (type == REDIS_LIST) {
listAddNodeTail((list*)o->ptr,ele); listAddNodeTail((list*)o->ptr,ele);
@ -3894,7 +3946,7 @@ static robj *rdbLoadObject(int type, FILE *fp) {
robj *ele; robj *ele;
double *score = zmalloc(sizeof(double)); double *score = zmalloc(sizeof(double));
if ((ele = rdbLoadStringObject(fp)) == NULL) return NULL; if ((ele = rdbLoadEncodedStringObject(fp)) == NULL) return NULL;
ele = tryObjectEncoding(ele); ele = tryObjectEncoding(ele);
if (rdbLoadDoubleValue(fp,score) == -1) return NULL; if (rdbLoadDoubleValue(fp,score) == -1) return NULL;
dictAdd(zs->dict,ele,score); dictAdd(zs->dict,ele,score);
@ -4850,7 +4902,7 @@ static void lremCommand(redisClient *c) {
robj *ele = listNodeValue(ln); robj *ele = listNodeValue(ln);
next = fromtail ? ln->prev : ln->next; next = fromtail ? ln->prev : ln->next;
if (compareStringObjects(ele,c->argv[3]) == 0) { if (equalStringObjects(ele,c->argv[3])) {
listDelNode(list,ln); listDelNode(list,ln);
server.dirty++; server.dirty++;
removed++; removed++;
@ -5454,7 +5506,7 @@ static int zslDelete(zskiplist *zsl, double score, robj *obj) {
/* We may have multiple elements with the same score, what we need /* We may have multiple elements with the same score, what we need
* is to find the element with both the right score and object. */ * is to find the element with both the right score and object. */
x = x->forward[0]; x = x->forward[0];
if (x && score == x->score && compareStringObjects(x->obj,obj) == 0) { if (x && score == x->score && equalStringObjects(x->obj,obj)) {
zslDeleteNode(zsl, x, update); zslDeleteNode(zsl, x, update);
zslFreeNode(x); zslFreeNode(x);
return 1; return 1;
@ -5559,7 +5611,7 @@ static unsigned long zslGetRank(zskiplist *zsl, double score, robj *o) {
} }
/* x might be equal to zsl->header, so test if obj is non-NULL */ /* x might be equal to zsl->header, so test if obj is non-NULL */
if (x->obj && compareStringObjects(x->obj,o) == 0) { if (x->obj && equalStringObjects(x->obj,o)) {
return rank; return rank;
} }
} }
@ -9623,7 +9675,7 @@ static int dontWaitForSwappedKey(redisClient *c, robj *key) {
/* Remove the key from the list of keys this client is waiting for. */ /* Remove the key from the list of keys this client is waiting for. */
listRewind(c->io_keys,&li); listRewind(c->io_keys,&li);
while ((ln = listNext(&li)) != NULL) { while ((ln = listNext(&li)) != NULL) {
if (compareStringObjects(ln->value,key) == 0) { if (equalStringObjects(ln->value,key)) {
listDelNode(c->io_keys,ln); listDelNode(c->io_keys,ln);
break; break;
} }
@ -9850,7 +9902,7 @@ static int listMatchPubsubPattern(void *a, void *b) {
pubsubPattern *pa = a, *pb = b; pubsubPattern *pa = a, *pb = b;
return (pa->client == pb->client) && return (pa->client == pb->client) &&
(compareStringObjects(pa->pattern,pb->pattern) == 0); (equalStringObjects(pa->pattern,pb->pattern));
} }
/* Subscribe a client to a channel. Returns 1 if the operation succeeded, or /* Subscribe a client to a channel. Returns 1 if the operation succeeded, or

15
sds.c
View File

@ -342,3 +342,18 @@ void sdsfreesplitres(sds *tokens, int count) {
sdsfree(tokens[count]); sdsfree(tokens[count]);
zfree(tokens); zfree(tokens);
} }
sds sdsfromlonglong(long long value) {
char buf[32], *p;
unsigned long long v;
v = (value < 0) ? -value : value;
p = buf+31; /* point to the last character */
do {
*p-- = '0'+(v%10);
v /= 10;
} while(v);
if (value < 0) *p-- = '-';
p++;
return sdsnewlen(p,32-(p-buf));
}

1
sds.h
View File

@ -68,5 +68,6 @@ sds *sdssplitlen(char *s, int len, char *sep, int seplen, int *count);
void sdsfreesplitres(sds *tokens, int count); void sdsfreesplitres(sds *tokens, int count);
void sdstolower(sds s); void sdstolower(sds s);
void sdstoupper(sds s); void sdstoupper(sds s);
sds sdsfromlonglong(long long value);
#endif #endif