1
0
Fork 0
mirror of https://github.com/dragonflydb/dragonfly.git synced 2024-12-15 17:51:06 +00:00

chore: reformat listpack according to valkey 8 (#3810)

Also add benchmarks for lpCompare code when list contains integers.

Signed-off-by: Roman Gershman <roman@dragonflydb.io>
This commit is contained in:
Roman Gershman 2024-09-27 12:22:08 +03:00 committed by GitHub
parent 6a13329523
commit 8ae71411bd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 152 additions and 133 deletions

View file

@ -9,6 +9,7 @@
#include <jsoncons/json.hpp>
#include <jsoncons_ext/jsonpath/jsonpath.hpp>
#include <random>
#include "base/gtest.h"
#include "base/logging.h"
@ -731,4 +732,69 @@ static void BM_UnpackSimd(benchmark::State& state) {
}
BENCHMARK(BM_UnpackSimd);
static void BM_LpCompare(benchmark::State& state) {
std::random_device rd;
uint8_t* lp = lpNew(0);
for (unsigned i = 0; i < 100; ++i) {
lp = lpAppendInteger(lp, rd() % (1ULL << 48));
}
string val = absl::StrCat(1ULL << 49);
while (state.KeepRunning()) {
uint8_t* elem = lpLast(lp);
while (elem) {
lpCompare(elem, reinterpret_cast<const uint8_t*>(val.data()), val.size());
elem = lpPrev(lp, elem);
}
}
lpFree(lp);
}
BENCHMARK(BM_LpCompare);
static void BM_LpCompareInt(benchmark::State& state) {
std::random_device rd;
uint8_t* lp = lpNew(0);
for (unsigned i = 0; i < 100; ++i) {
lp = lpAppendInteger(lp, rd() % (1ULL << 48));
}
int64_t val = 1ULL << 49;
while (state.KeepRunning()) {
uint8_t* elem = lpLast(lp);
int64_t sz;
while (elem) {
DCHECK_NE(0xFF, *elem);
unsigned char* value = lpGet(elem, &sz, NULL);
if (!value) {
int res = sz == val;
benchmark::DoNotOptimize(res);
}
elem = lpPrev(lp, elem);
}
}
lpFree(lp);
}
BENCHMARK(BM_LpCompareInt);
static void BM_LpGet(benchmark::State& state) {
uint8_t* lp = lpNew(0);
int64_t val = -1;
for (unsigned i = 0; i < 60; ++i) {
lp = lpAppendInteger(lp, val);
val *= 2;
}
while (state.KeepRunning()) {
uint8_t* elem = lpLast(lp);
int64_t sz;
while (elem) {
unsigned char* value = lpGet(elem, &sz, NULL);
CHECK(!value && sz < 0);
elem = lpPrev(lp, elem);
}
}
lpFree(lp);
}
BENCHMARK(BM_LpGet);
} // namespace dfly

View file

@ -4,8 +4,7 @@
*
* https://github.com/antirez/listpack
*
* Copyright (c) 2017, Salvatore Sanfilippo <antirez at gmail dot com>
* Copyright (c) 2020, Redis Labs, Inc
* Copyright (c) 2017,2020, Redis Ltd.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -41,6 +40,7 @@
#include <stdio.h>
#include <assert.h>
#include "config.h"
#include "listpack.h"
#include "util.h"
#include "zmalloc.h"
@ -49,7 +49,6 @@
#define LP_HDR_NUMELE_UNKNOWN UINT16_MAX
#define LP_MAX_INT_ENCODING_LEN 9
#define LP_MAX_BACKLEN_SIZE 5
#define LP_MAX_ENTRY_BACKLEN 34359738367ULL
#define LP_ENCODING_INT 0
#define LP_ENCODING_STRING 1
@ -99,26 +98,23 @@
#define LP_ENCODING_6BIT_STR_LEN(p) ((p)[0] & 0x3F)
#define LP_ENCODING_12BIT_STR_LEN(p) ((((p)[0] & 0xF) << 8) | (p)[1])
#define LP_ENCODING_32BIT_STR_LEN(p) (((uint32_t)(p)[1]<<0) | \
((uint32_t)(p)[2]<<8) | \
((uint32_t)(p)[3]<<16) | \
((uint32_t)(p)[4]<<24))
#define LP_ENCODING_32BIT_STR_LEN(p) \
(((uint32_t)(p)[1] << 0) | ((uint32_t)(p)[2] << 8) | ((uint32_t)(p)[3] << 16) | ((uint32_t)(p)[4] << 24))
#define lpGetTotalBytes(p) (((uint32_t)(p)[0]<<0) | \
((uint32_t)(p)[1]<<8) | \
((uint32_t)(p)[2]<<16) | \
((uint32_t)(p)[3]<<24))
#define lpGetTotalBytes(p) \
(((uint32_t)(p)[0] << 0) | ((uint32_t)(p)[1] << 8) | ((uint32_t)(p)[2] << 16) | ((uint32_t)(p)[3] << 24))
#define lpGetNumElements(p) (((uint32_t)(p)[4]<<0) | \
((uint32_t)(p)[5]<<8))
#define lpSetTotalBytes(p,v) do { \
#define lpGetNumElements(p) (((uint32_t)(p)[4] << 0) | ((uint32_t)(p)[5] << 8))
#define lpSetTotalBytes(p, v) \
do { \
(p)[0] = (v)&0xff; \
(p)[1] = ((v)>>8)&0xff; \
(p)[2] = ((v)>>16)&0xff; \
(p)[3] = ((v)>>24)&0xff; \
} while(0)
#define lpSetNumElements(p,v) do { \
#define lpSetNumElements(p, v) \
do { \
(p)[4] = (v)&0xff; \
(p)[5] = ((v)>>8)&0xff; \
} while(0)
@ -128,13 +124,15 @@
* that this element is valid, so it can be freely used.
* Generally functions such lpNext and lpDelete assume the input pointer is
* already validated (since it's the return value of another function). */
#define ASSERT_INTEGRITY(lp, p) do { \
#define ASSERT_INTEGRITY(lp, p) \
do { \
assert((p) >= (lp)+LP_HDR_SIZE && (p) < (lp)+lpGetTotalBytes((lp))); \
} while (0)
/* Similar to the above, but validates the entire element length rather than just
* it's pointer. */
#define ASSERT_INTEGRITY_LEN(lp, p, len) do { \
#define ASSERT_INTEGRITY_LEN(lp, p, len) \
do { \
assert((p) >= (lp)+LP_HDR_SIZE && (p)+(len) < (lp)+lpGetTotalBytes((lp))); \
} while (0)
@ -145,8 +143,7 @@ static inline void lpAssertValidEntry(unsigned char* lp, size_t lpbytes, unsigne
#define LISTPACK_MAX_SAFETY_SIZE (1<<30)
int lpSafeToAdd(unsigned char* lp, size_t add) {
size_t len = lp? lpGetTotalBytes(lp): 0;
if (len + add > LISTPACK_MAX_SAFETY_SIZE)
return 0;
if (len + add > LISTPACK_MAX_SAFETY_SIZE) return 0;
return 1;
}
@ -166,11 +163,11 @@ int lpSafeToAdd(unsigned char* lp, size_t add) {
*
* -----------------------------------------------------------------------------
*
* Credits: this function was adapted from the Redis source code, file
* Credits: this function was adapted from the Redis OSS source code, file
* "utils.c", function string2ll(), and is copyright:
*
* Copyright(C) 2011, Pieter Noordhuis
* Copyright(C) 2011, Salvatore Sanfilippo
* Copyright(C) 2011, Redis Ltd.
*
* The function is released under the BSD 3-clause license.
*/
@ -181,8 +178,7 @@ int lpStringToInt64(const char *s, unsigned long slen, int64_t *value) {
uint64_t v;
/* Abort if length indicates this cannot possibly be an int */
if (slen == 0)
return 0;
if (slen == 0 || slen >= LONG_STR_SIZE) return 0;
/* Special case: first and only digit is 0. */
if (slen == 1 && p[0] == '0') {
@ -192,17 +188,18 @@ int lpStringToInt64(const char *s, unsigned long slen, int64_t *value) {
if (p[0] == '-') {
negative = 1;
p++; plen++;
p++;
plen++;
/* Abort on only a negative sign. */
if (plen == slen)
return 0;
if (plen == slen) return 0;
}
/* First digit should be 1-9, otherwise the string should just be 0. */
if (p[0] >= '1' && p[0] <= '9') {
v = p[0]-'0';
p++; plen++;
p++;
plen++;
} else {
return 0;
}
@ -216,12 +213,12 @@ int lpStringToInt64(const char *s, unsigned long slen, int64_t *value) {
return 0;
v += p[0]-'0';
p++; plen++;
p++;
plen++;
}
/* Return if not all bytes were used. */
if (plen < slen)
return 0;
if (plen < slen) return 0;
if (negative) {
if (v > ((uint64_t)(-(INT64_MIN+1))+1)) /* Overflow. */
@ -333,9 +330,12 @@ static inline int lpEncodeGetType(const unsigned char *ele, uint32_t size, unsig
lpEncodeIntegerGetType(v, intenc, enclen);
return LP_ENCODING_INT;
} else {
if (size < 64) *enclen = 1+size;
else if (size < 4096) *enclen = 2+size;
else *enclen = 5+(uint64_t)size;
if (size < 64)
*enclen = 1 + size;
else if (size < 4096)
*enclen = 2 + size;
else
*enclen = 5 + (uint64_t)size;
return LP_ENCODING_STRING;
}
}
@ -569,10 +569,9 @@ unsigned long lpLength(unsigned char *lp) {
* this lib.
*
* Similarly, there is no error returned since the listpack normally can be
* assumed to be valid, so that would be a very high API cost. However a function
* in order to check the integrity of the listpack at load time is provided,
* check lpIsValid(). */
static inline unsigned char *lpGetWithSize(unsigned char *p, int64_t *count, unsigned char *intbuf, uint64_t *entry_size) {
* assumed to be valid, so that would be a very high API cost. */
static inline unsigned char *
lpGetWithSize(unsigned char *p, int64_t *count, unsigned char *intbuf, uint64_t *entry_size) {
int64_t val;
uint64_t uval, negstart, negmax;
@ -592,35 +591,23 @@ static inline unsigned char *lpGetWithSize(unsigned char *p, int64_t *count, uns
negmax = 8191;
if (entry_size) *entry_size = LP_ENCODING_13BIT_INT_ENTRY_SIZE;
} else if (LP_ENCODING_IS_16BIT_INT(p[0])) {
uval = (uint64_t)p[1] |
(uint64_t)p[2]<<8;
uval = (uint64_t)p[1] | (uint64_t)p[2] << 8;
negstart = (uint64_t)1<<15;
negmax = UINT16_MAX;
if (entry_size) *entry_size = LP_ENCODING_16BIT_INT_ENTRY_SIZE;
} else if (LP_ENCODING_IS_24BIT_INT(p[0])) {
uval = (uint64_t)p[1] |
(uint64_t)p[2]<<8 |
(uint64_t)p[3]<<16;
uval = (uint64_t)p[1] | (uint64_t)p[2] << 8 | (uint64_t)p[3] << 16;
negstart = (uint64_t)1<<23;
negmax = UINT32_MAX>>8;
if (entry_size) *entry_size = LP_ENCODING_24BIT_INT_ENTRY_SIZE;
} else if (LP_ENCODING_IS_32BIT_INT(p[0])) {
uval = (uint64_t)p[1] |
(uint64_t)p[2]<<8 |
(uint64_t)p[3]<<16 |
(uint64_t)p[4]<<24;
uval = (uint64_t)p[1] | (uint64_t)p[2] << 8 | (uint64_t)p[3] << 16 | (uint64_t)p[4] << 24;
negstart = (uint64_t)1<<31;
negmax = UINT32_MAX;
if (entry_size) *entry_size = LP_ENCODING_32BIT_INT_ENTRY_SIZE;
} else if (LP_ENCODING_IS_64BIT_INT(p[0])) {
uval = (uint64_t)p[1] |
(uint64_t)p[2]<<8 |
(uint64_t)p[3]<<16 |
(uint64_t)p[4]<<24 |
(uint64_t)p[5]<<32 |
(uint64_t)p[6]<<40 |
(uint64_t)p[7]<<48 |
(uint64_t)p[8]<<56;
uval = (uint64_t)p[1] | (uint64_t)p[2] << 8 | (uint64_t)p[3] << 16 | (uint64_t)p[4] << 24 |
(uint64_t)p[5] << 32 | (uint64_t)p[6] << 40 | (uint64_t)p[7] << 48 | (uint64_t)p[8] << 56;
negstart = (uint64_t)1<<63;
negmax = UINT64_MAX;
if (entry_size) *entry_size = LP_ENCODING_64BIT_INT_ENTRY_SIZE;
@ -686,8 +673,7 @@ unsigned char *lpGetValue(unsigned char *p, unsigned int *slen, long long *lval)
/* Find pointer to the entry equal to the specified entry. Skip 'skip' entries
* between every comparison. Returns NULL when the field could not be found. */
unsigned char *lpFind(unsigned char *lp, unsigned char *p, unsigned char *s,
uint32_t slen, unsigned int skip) {
unsigned char *lpFind(unsigned char *lp, unsigned char *p, unsigned char *s, uint32_t slen, unsigned int skip) {
int skipcnt = 0;
unsigned char vencoding = 0;
unsigned char *value;
@ -735,7 +721,7 @@ unsigned char *lpFind(unsigned char *lp, unsigned char *p, unsigned char *s,
/* Skip entry */
skipcnt--;
/* Move to next entry, avoid use `lpNext` due to `ASSERT_INTEGRITY` in
/* Move to next entry, avoid use `lpNext` due to `lpAssertValidEntry` in
* `lpNext` will call `lpBytes`, will cause performance degradation */
p = lpSkip(p);
}
@ -787,12 +773,12 @@ unsigned char *lpInsert(unsigned char *lp, const unsigned char *elestr, unsigned
unsigned char backlen[LP_MAX_BACKLEN_SIZE];
uint64_t enclen; /* The length of the encoded element. */
int delete = (elestr == NULL && eleint == NULL);
int del_ele = (elestr == NULL && eleint == NULL);
/* when deletion, it is conceptually replacing the element with a
* zero-length element. So whatever we get passed as 'where', set
* it to LP_REPLACE. */
if (delete) where = LP_REPLACE;
if (del_ele) where = LP_REPLACE;
/* If we need to insert after the current element, we just jump to the
* next element (that could be the EOF one) and handle the case of
@ -831,7 +817,7 @@ unsigned char *lpInsert(unsigned char *lp, const unsigned char *elestr, unsigned
/* We need to also encode the backward-parsable length of the element
* and append it to the end: this allows to traverse the listpack from
* the end to the start. */
unsigned long backlen_size = (!delete) ? lpEncodeBacklen(backlen,enclen) : 0;
unsigned long backlen_size = (!del_ele) ? lpEncodeBacklen(backlen, enclen) : 0;
uint64_t old_listpack_bytes = lpGetTotalBytes(lp);
uint32_t replaced_len = 0;
if (where == LP_REPLACE) {
@ -840,8 +826,7 @@ unsigned char *lpInsert(unsigned char *lp, const unsigned char *elestr, unsigned
ASSERT_INTEGRITY_LEN(lp, p, replaced_len);
}
uint64_t new_listpack_bytes = old_listpack_bytes + enclen + backlen_size
- replaced_len;
uint64_t new_listpack_bytes = old_listpack_bytes + enclen + backlen_size - replaced_len;
if (new_listpack_bytes > UINT32_MAX) return NULL;
/* We now need to reallocate in order to make space or shrink the
@ -853,9 +838,8 @@ unsigned char *lpInsert(unsigned char *lp, const unsigned char *elestr, unsigned
unsigned char *dst = lp + poff; /* May be updated after reallocation. */
/* Realloc before: we need more room. */
if (new_listpack_bytes > old_listpack_bytes &&
new_listpack_bytes > zmalloc_size(lp)) {
if ((lp = zrealloc(lp,new_listpack_bytes)) == NULL) return NULL;
if (new_listpack_bytes > old_listpack_bytes && new_listpack_bytes > zmalloc_size(lp)) {
if ((lp = zrealloc(lp, new_listpack_bytes)) == NULL) return NULL;
dst = lp + poff;
}
@ -864,10 +848,7 @@ unsigned char *lpInsert(unsigned char *lp, const unsigned char *elestr, unsigned
if (where == LP_BEFORE) {
memmove(dst+enclen+backlen_size,dst,old_listpack_bytes-poff);
} else { /* LP_REPLACE. */
long lendiff = (enclen+backlen_size)-replaced_len;
memmove(dst+replaced_len+lendiff,
dst+replaced_len,
old_listpack_bytes-poff-replaced_len);
memmove(dst + enclen + backlen_size, dst + replaced_len, old_listpack_bytes - poff - replaced_len);
}
/* Realloc after: we need to free space. */
@ -881,13 +862,15 @@ unsigned char *lpInsert(unsigned char *lp, const unsigned char *elestr, unsigned
*newp = dst;
/* In case of deletion, set 'newp' to NULL if the next element is
* the EOF element. */
if (delete && dst[0] == LP_EOF) *newp = NULL;
if (del_ele && dst[0] == LP_EOF) *newp = NULL;
}
if (!delete) {
if (!del_ele) {
if (enctype == LP_ENCODING_INT) {
memcpy(dst,eleint,enclen);
} else {
} else if (elestr) {
lpEncodeString(dst,elestr,size);
} else {
valkey_unreachable();
}
dst += enclen;
memcpy(dst,backlen,backlen_size);
@ -895,10 +878,10 @@ unsigned char *lpInsert(unsigned char *lp, const unsigned char *elestr, unsigned
}
/* Update header. */
if (where != LP_REPLACE || delete) {
if (where != LP_REPLACE || del_ele) {
uint32_t num_elements = lpGetNumElements(lp);
if (num_elements != LP_HDR_NUMELE_UNKNOWN) {
if (!delete)
if (!del_ele)
lpSetNumElements(lp,num_elements+1);
else
lpSetNumElements(lp,num_elements-1);
@ -1026,8 +1009,7 @@ unsigned char *lpDeleteRangeWithEntry(unsigned char *lp, unsigned char **p, unsi
memmove(first, tail, eofptr - tail + 1);
lpSetTotalBytes(lp, bytes - (tail - first));
uint32_t numele = lpGetNumElements(lp);
if (numele != LP_HDR_NUMELE_UNKNOWN)
lpSetNumElements(lp, numele-deleted);
if (numele != LP_HDR_NUMELE_UNKNOWN) lpSetNumElements(lp, numele - deleted);
lp = lpShrinkToFit(lp);
/* Store the entry. */
@ -1082,12 +1064,10 @@ unsigned char *lpDeleteRange(unsigned char *lp, long index, unsigned long num) {
* input listpack argument equal to newly reallocated listpack return value. */
unsigned char *lpMerge(unsigned char **first, unsigned char **second) {
/* If any params are null, we can't merge, so NULL. */
if (first == NULL || *first == NULL || second == NULL || *second == NULL)
return NULL;
if (first == NULL || *first == NULL || second == NULL || *second == NULL) return NULL;
/* Can't merge same list into itself. */
if (*first == *second)
return NULL;
if (*first == *second) return NULL;
size_t first_bytes = lpBytes(*first);
unsigned long first_len = lpLength(*first);
@ -1131,17 +1111,13 @@ unsigned char *lpMerge(unsigned char **first, unsigned char **second) {
/* append == appending to target */
/* Copy source after target (copying over original [END]):
* [TARGET - END, SOURCE - HEADER] */
memcpy(target + target_bytes - 1,
source + LP_HDR_SIZE,
source_bytes - LP_HDR_SIZE);
memcpy(target + target_bytes - 1, source + LP_HDR_SIZE, source_bytes - LP_HDR_SIZE);
} else {
/* !append == prepending to target */
/* Move target *contents* exactly size of (source - [END]),
* then copy source into vacated space (source - [END]):
* [SOURCE - END, TARGET - HEADER] */
memmove(target + source_bytes - 1,
target + LP_HDR_SIZE,
target_bytes - LP_HDR_SIZE);
memmove(target + source_bytes - 1, target + LP_HDR_SIZE, target_bytes - LP_HDR_SIZE);
memcpy(target, source, source_bytes - 1);
}
@ -1227,16 +1203,12 @@ unsigned char *lpValidateFirst(unsigned char *lp) {
* The input argument 'pp' is a reference to the current record and is advanced on exit.
* Returns 1 if valid, 0 if invalid. */
int lpValidateNext(unsigned char *lp, unsigned char **pp, size_t lpbytes) {
#define OUT_OF_RANGE(p) ( \
(p) < lp + LP_HDR_SIZE || \
(p) > lp + lpbytes - 1)
#define OUT_OF_RANGE(p) ((p) < lp + LP_HDR_SIZE || (p) > lp + lpbytes - 1)
unsigned char *p = *pp;
if (!p)
return 0;
if (!p) return 0;
/* Before accessing p, make sure it's valid. */
if (OUT_OF_RANGE(p))
return 0;
if (OUT_OF_RANGE(p)) return 0;
if (*p == LP_EOF) {
*pp = NULL;
@ -1245,12 +1217,10 @@ int lpValidateNext(unsigned char *lp, unsigned char **pp, size_t lpbytes) {
/* check that we can read the encoded size */
uint32_t lenbytes = lpCurrentEncodedSizeBytes(p);
if (!lenbytes)
return 0;
if (!lenbytes) return 0;
/* make sure the encoded entry length doesn't reach outside the edge of the listpack */
if (OUT_OF_RANGE(p + lenbytes))
return 0;
if (OUT_OF_RANGE(p + lenbytes)) return 0;
/* get the entry length and encoded backlen. */
unsigned long entrylen = lpCurrentEncodedSizeUnsafe(p);
@ -1258,16 +1228,14 @@ int lpValidateNext(unsigned char *lp, unsigned char **pp, size_t lpbytes) {
entrylen += encodedBacklen;
/* make sure the entry doesn't reach outside the edge of the listpack */
if (OUT_OF_RANGE(p + entrylen))
return 0;
if (OUT_OF_RANGE(p + entrylen)) return 0;
/* move to the next entry */
p += entrylen;
/* make sure the encoded length at the end patches the one at the beginning. */
uint64_t prevlen = lpDecodeBacklen(p-1);
if (prevlen + encodedBacklen != entrylen)
return 0;
if (prevlen + encodedBacklen != entrylen) return 0;
*pp = p;
return 1;
@ -1282,23 +1250,18 @@ static inline void lpAssertValidEntry(unsigned char* lp, size_t lpbytes, unsigne
/* Validate the integrity of the data structure.
* when `deep` is 0, only the integrity of the header is validated.
* when `deep` is 1, we scan all the entries one by one. */
int lpValidateIntegrity(unsigned char *lp, size_t size, int deep,
listpackValidateEntryCB entry_cb, void *cb_userdata) {
int lpValidateIntegrity(unsigned char *lp, size_t size, int deep, listpackValidateEntryCB entry_cb, void *cb_userdata) {
/* Check that we can actually read the header. (and EOF) */
if (size < LP_HDR_SIZE + 1)
return 0;
if (size < LP_HDR_SIZE + 1) return 0;
/* Check that the encoded size in the header must match the allocated size. */
size_t bytes = lpGetTotalBytes(lp);
if (bytes != size)
return 0;
if (bytes != size) return 0;
/* The last byte must be the terminator. */
if (lp[size-1] != LP_EOF)
return 0;
if (lp[size - 1] != LP_EOF) return 0;
if (!deep)
return 1;
if (!deep) return 1;
/* Validate the individual entries. */
uint32_t count = 0;
@ -1309,23 +1272,19 @@ int lpValidateIntegrity(unsigned char *lp, size_t size, int deep,
/* Validate this entry and move to the next entry in advance
* to avoid callback crash due to corrupt listpack. */
if (!lpValidateNext(lp, &p, bytes))
return 0;
if (!lpValidateNext(lp, &p, bytes)) return 0;
/* Optionally let the caller validate the entry too. */
if (entry_cb && !entry_cb(prev, numele, cb_userdata))
return 0;
if (entry_cb && !entry_cb(prev, numele, cb_userdata)) return 0;
count++;
}
/* Make sure 'p' really does point to the end of the listpack. */
if (p != lp + size - 1)
return 0;
if (p != lp + size - 1) return 0;
/* Check that the count in the header is correct */
if (numele != LP_HDR_NUMELE_UNKNOWN && numele != count)
return 0;
if (numele != LP_HDR_NUMELE_UNKNOWN && numele != count) return 0;
return 1;
}
@ -1345,8 +1304,7 @@ unsigned int lpCompare(unsigned char *p, const unsigned char *s, uint32_t slen)
* string 's' and compare it to 'sval', it's much faster than convert
* integer to string and comparing. */
int64_t sval;
if (lpStringToInt64((const char*)s, slen, &sval))
return sz == sval;
if (lpStringToInt64((const char *)s, slen, &sval)) return sz == sval;
}
return 0;
@ -1428,8 +1386,7 @@ void lpRandomPairs(unsigned char *lp, unsigned int count, listpackEntry *keys, l
while (pickindex < count && lpindex == picks[pickindex].index) {
int storeorder = picks[pickindex].order;
lpSaveValue(key, klen, klval, &keys[storeorder]);
if (vals)
lpSaveValue(value, vlen, vlval, &vals[storeorder]);
if (vals) lpSaveValue(value, vlen, vlval, &vals[storeorder]);
pickindex++;
}
lpindex += 2;
@ -1451,8 +1408,7 @@ unsigned int lpRandomPairsUnique(unsigned char *lp, unsigned int count, listpack
long long klval = 0;
unsigned int total_size = lpLength(lp)/2;
unsigned int index = 0;
if (count > total_size)
count = total_size;
if (count > total_size) count = total_size;
/* To only iterate once, every time we try to pick a member, the probability
* we pick it is the quotient of the count left we want to pick and the
@ -1498,8 +1454,7 @@ void lpRepr(unsigned char *lp) {
uint32_t encoded_size_bytes = lpCurrentEncodedSizeBytes(p);
uint32_t encoded_size = lpCurrentEncodedSizeUnsafe(p);
unsigned long back_len = lpEncodeBacklen(NULL, encoded_size);
printf(
"{\n"
printf("{\n"
"\taddr: 0x%08lx,\n"
"\tindex: %2d,\n"
"\toffset: %1lu,\n"
@ -1507,12 +1462,7 @@ void lpRepr(unsigned char *lp) {
"\thdrlen: %3u,\n"
"\tbacklen: %2lu,\n"
"\tpayload: %1u\n",
(long unsigned)p,
index,
(unsigned long) (p-lp),
encoded_size + back_len,
encoded_size_bytes,
back_len,
(long unsigned)p, index, (unsigned long)(p - lp), encoded_size + back_len, encoded_size_bytes, back_len,
encoded_size - encoded_size_bytes);
printf("\tbytes: ");
for (unsigned int i = 0; i < (encoded_size + back_len); i++) {

View file

@ -81,6 +81,9 @@ int ld2string(char *buf, size_t len, long double value, ld2string_mode mode);
#define LRU_CLOCK_MAX ((1<<LRU_BITS)-1) /* Max value of obj->lru */
#define LRU_CLOCK_RESOLUTION 1000 /* LRU clock resolution in ms */
/* Bytes needed for long -> str + '\0' */
#define LONG_STR_SIZE 21
void serverLog(int level, const char *fmt, ...);
void _serverPanic(const char *file, int line, const char *msg, ...);
void _serverAssert(const char *estr, const char *file, int line);