]> git.saurik.com Git - redis.git/commitdiff
long long to string conversion speedup applied in other places as well. Still the...
authorantirez <antirez@gmail.com>
Tue, 11 May 2010 12:13:53 +0000 (14:13 +0200)
committerantirez <antirez@gmail.com>
Tue, 11 May 2010 12:13:53 +0000 (14:13 +0200)
redis.c
sds.c
sds.h

diff --git a/redis.c b/redis.c
index 1ab854caefd64e35f84338ea19d27e925615ab5c..35020a91212b923a71eb4b25d88cd489a9643cda 100644 (file)
--- a/redis.c
+++ b/redis.c
@@ -1023,6 +1023,30 @@ static long long memtoll(const char *p, int *err) {
     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, ...) {
     va_list ap;
     FILE *fp;
@@ -1126,7 +1150,7 @@ static unsigned int dictEncObjHash(const void *key) {
             char buf[32];
             int len;
 
-            len = snprintf(buf,32,"%ld",(long)o->ptr);
+            len = ll2string(buf,32,(long)o->ptr);
             return dictGenHashFunction((unsigned char*)buf, len);
         } else {
             unsigned int hash;
@@ -2897,19 +2921,7 @@ static robj *createStringObjectFromLongLong(long long value) {
             o->encoding = REDIS_ENCODING_INT;
             o->ptr = (void*)((long)value);
         } else {
-            char buf[32], *p;
-            char *c = "0123456789";
-            unsigned long v;
-
-            v = (value < 0) ? -value : value;
-            p = buf+31; /* point to the last character */
-            while(v) {
-                *p-- = c[v%10];
-                v /= 10;
-            }
-            if (value < 0) *p-- = '-';
-            p++;
-            o = createObject(REDIS_STRING,sdsnewlen(p,32-(p-buf+1)));
+            o = createObject(REDIS_STRING,sdsfromlonglong(value));
         }
     }
     return o;
@@ -3124,7 +3136,7 @@ static int isStringRepresentableAsLong(sds s, long *longval) {
 
     value = strtol(s, &endptr, 10);
     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
      * then it's not possible to encode the string as integer */
@@ -3177,7 +3189,7 @@ static robj *getDecodedObject(robj *o) {
     if (o->type == REDIS_STRING && o->encoding == REDIS_ENCODING_INT) {
         char buf[32];
 
-        snprintf(buf,32,"%ld",(long)o->ptr);
+        ll2string(buf,32,(long)o->ptr);
         dec = createStringObject(buf,strlen(buf));
         return dec;
     } else {
@@ -3187,7 +3199,7 @@ static robj *getDecodedObject(robj *o) {
 
 /* Compare two string objects via strcmp() or alike.
  * 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().
  *
  * Important note: if objects are not integer encoded, but binary-safe strings,
@@ -3200,14 +3212,14 @@ static int compareStringObjects(robj *a, robj *b) {
 
     if (a == b) return 0;
     if (a->encoding != REDIS_ENCODING_RAW) {
-        snprintf(bufa,sizeof(bufa),"%ld",(long) a->ptr);
+        ll2string(bufa,sizeof(bufa),(long) a->ptr);
         astr = bufa;
         bothsds = 0;
     } else {
         astr = a->ptr;
     }
     if (b->encoding != REDIS_ENCODING_RAW) {
-        snprintf(bufb,sizeof(bufb),"%ld",(long) b->ptr);
+        ll2string(bufb,sizeof(bufb),(long) b->ptr);
         bstr = bufb;
         bothsds = 0;
     } else {
@@ -3235,7 +3247,7 @@ static size_t stringObjectLen(robj *o) {
     } else {
         char buf[32];
 
-        return snprintf(buf,32,"%ld",(long)o->ptr);
+        return ll2string(buf,32,(long)o->ptr);
     }
 }
 
@@ -3376,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 */
     value = strtoll(s, &endptr, 10);
     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
      * then it's not possible to encode the string as integer */
diff --git a/sds.c b/sds.c
index 6e6fa508f3dedeaf56d517e3f72ccd03287f21dd..feb1a6212e657661dbe0a1de5a9b028b1e79e7af 100644 (file)
--- a/sds.c
+++ b/sds.c
@@ -342,3 +342,18 @@ void sdsfreesplitres(sds *tokens, int count) {
         sdsfree(tokens[count]);
     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));
+}
diff --git a/sds.h b/sds.h
index 02bcedcfc487a75fd9e360f76b07c6823571fc63..8b632ff920570d3770815a38109b5abec06dbea4 100644 (file)
--- a/sds.h
+++ b/sds.h
@@ -68,5 +68,6 @@ sds *sdssplitlen(char *s, int len, char *sep, int seplen, int *count);
 void sdsfreesplitres(sds *tokens, int count);
 void sdstolower(sds s);
 void sdstoupper(sds s);
+sds sdsfromlonglong(long long value);
 
 #endif