summaryrefslogtreecommitdiff
path: root/src/rdb.c
diff options
context:
space:
mode:
authorOran Agra <oran@redislabs.com>2022-04-17 17:16:46 +0300
committerGitHub <noreply@github.com>2022-04-17 17:16:46 +0300
commit0c4733c8d7c50e0b0dc3373733fddfff3f62dda0 (patch)
tree5ecd20be1f6f9397539d42558b84f74a0800d87a /src/rdb.c
parentf49ff156ecd62aee104cff9f88fb62948575e6b0 (diff)
downloadredis-0c4733c8d7c50e0b0dc3373733fddfff3f62dda0.tar.gz
Optimize integer zset scores in listpack (converting to string and back) (#10486)
When the score doesn't have fractional part, and can be stored as an integer, we use the integer capabilities of listpack to store it, rather than convert it to string. This already existed before this PR (lpInsert dose that conversion implicitly). But to do that, we would have first converted the score from double to string (calling `d2string`), then pass the string to `lpAppend` which identified it as being an integer and convert it back to an int. Now, instead of converting it to a string, we store it using lpAppendInteger`. Unrelated: --- * Fix the double2ll range check (negative and positive ranges, and also the comparison operands were slightly off. but also, the range could be made much larger, see comment). * Unify the double to string conversion code in rdb.c with the one in util.c * Small optimization in lpStringToInt64, don't attempt to convert strings that are obviously too long. Benchmark; --- Up to 20% improvement in certain tight loops doing zzlInsert with large integers. (if listpack is pre-allocated to avoid realloc, and insertion is sorted from largest to smaller)
Diffstat (limited to 'src/rdb.c')
-rw-r--r--src/rdb.c19
1 files changed, 4 insertions, 15 deletions
diff --git a/src/rdb.c b/src/rdb.c
index 7f2225dfb..62ec5bbb2 100644
--- a/src/rdb.c
+++ b/src/rdb.c
@@ -588,22 +588,11 @@ int rdbSaveDoubleValue(rio *rdb, double val) {
len = 1;
buf[0] = (val < 0) ? 255 : 254;
} else {
-#if (DBL_MANT_DIG >= 52) && (LLONG_MAX == 0x7fffffffffffffffLL)
- /* Check if the float is in a safe range to be casted into a
- * long long. We are assuming that long long is 64 bit here.
- * Also we are assuming that there are no implementations around where
- * double has precision < 52 bit.
- *
- * Under this assumptions we test if a double is inside an interval
- * where casting to long long is safe. Then using two castings we
- * make sure the decimal part is zero. If all this is true we use
- * integer printing function that is much faster. */
- double min = -4503599627370495; /* (2^52)-1 */
- double max = 4503599627370496; /* -(2^52) */
- if (val > min && val < max && val == ((double)((long long)val)))
- ll2string((char*)buf+1,sizeof(buf)-1,(long long)val);
+ long long lvalue;
+ /* Integer printing function is much faster, check if we can safely use it. */
+ if (double2ll(val, &lvalue))
+ ll2string((char*)buf+1,sizeof(buf)-1,lvalue);
else
-#endif
snprintf((char*)buf+1,sizeof(buf)-1,"%.17g",val);
buf[0] = strlen((char*)buf+1);
len = buf[0]+1;