HLLSELFTEST command implemented.
To test the bitfield array of counters set/get macros from the Redis Tcl suite is hard, so a specialized command that is able to test the internals was developed.
This commit is contained in:
parent
0609380603
commit
552eb5407a
@ -107,7 +107,7 @@ endif
|
|||||||
|
|
||||||
REDIS_SERVER_NAME=redis-server
|
REDIS_SERVER_NAME=redis-server
|
||||||
REDIS_SENTINEL_NAME=redis-sentinel
|
REDIS_SENTINEL_NAME=redis-sentinel
|
||||||
REDIS_SERVER_OBJ=adlist.o ae.o anet.o dict.o redis.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o
|
REDIS_SERVER_OBJ=adlist.o ae.o anet.o dict.o redis.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o
|
||||||
REDIS_CLI_NAME=redis-cli
|
REDIS_CLI_NAME=redis-cli
|
||||||
REDIS_CLI_OBJ=anet.o sds.o adlist.o redis-cli.o zmalloc.o release.o anet.o ae.o crc64.o
|
REDIS_CLI_OBJ=anet.o sds.o adlist.o redis-cli.o zmalloc.o release.o anet.o ae.o crc64.o
|
||||||
REDIS_BENCHMARK_NAME=redis-benchmark
|
REDIS_BENCHMARK_NAME=redis-benchmark
|
||||||
|
@ -53,6 +53,7 @@
|
|||||||
|
|
||||||
#define REDIS_HLL_REGISTERS 16384
|
#define REDIS_HLL_REGISTERS 16384
|
||||||
#define REDIS_HLL_BITS 6
|
#define REDIS_HLL_BITS 6
|
||||||
|
#define REDIS_HLL_REGISTER_MAX ((1<<REDIS_HLL_BITS)-1)
|
||||||
#define REDIS_HLL_SIZE ((REDIS_HLL_REGISTERS*REDIS_HLL_BITS+7)/8)
|
#define REDIS_HLL_SIZE ((REDIS_HLL_REGISTERS*REDIS_HLL_BITS+7)/8)
|
||||||
|
|
||||||
/* =========================== Low level bit macros ========================= */
|
/* =========================== Low level bit macros ========================= */
|
||||||
@ -158,18 +159,60 @@
|
|||||||
|
|
||||||
/* Set the value of the register at position 'regnum' to 'val'.
|
/* Set the value of the register at position 'regnum' to 'val'.
|
||||||
* 'p' is an array of unsigned bytes. */
|
* 'p' is an array of unsigned bytes. */
|
||||||
#define HLL_SET_REGISTER(val,p,regnum) do { \
|
#define HLL_SET_REGISTER(p,regnum,val) do { \
|
||||||
int _byte = regnum*REDIS_HLL_BITS/8; \
|
int _byte = regnum*REDIS_HLL_BITS/8; \
|
||||||
int _leftshift = regnum*REDIS_HLL_BITS&7; \
|
int _leftshift = regnum*REDIS_HLL_BITS&7; \
|
||||||
int _rightshift = 8 - _leftshift; \
|
int _rightshift = 8 - _leftshift; \
|
||||||
unsigned int m1 = 255, m2 = (1<<REDIS_HLL_BITS)-1; \
|
unsigned int m1 = 255, m2 = REDIS_HLL_REGISTER_MAX; \
|
||||||
p[byte] &= m1 << _rightshift; \
|
p[_byte] &= m1 << _rightshift; \
|
||||||
p[byte] |= val >> _leftshift; \
|
p[_byte] |= val >> _leftshift; \
|
||||||
p[byte+1] &= ~(m2 << _rightshift); \
|
p[_byte+1] &= ~(m2 << _rightshift); \
|
||||||
p[byte+1] |= val << _rightshift; \
|
p[_byte+1] |= val << _rightshift; \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
/* ========================= HyperLogLog algorithm ========================= */
|
/* ========================= HyperLogLog algorithm ========================= */
|
||||||
|
|
||||||
/* ========================== HyperLogLog commands ========================== */
|
/* ========================== HyperLogLog commands ========================== */
|
||||||
|
|
||||||
|
/* This command performs a self-test of the HLL registers implementation.
|
||||||
|
* Something that is not easy to test from within the outside.
|
||||||
|
*
|
||||||
|
* The test is conceived to test that the different counters of our data
|
||||||
|
* structure are accessible and that setting their values both result in
|
||||||
|
* the correct value to be retained and not affect adjacent values. */
|
||||||
|
|
||||||
|
#define REDIS_HLL_TEST_CYCLES 1000
|
||||||
|
void hllSelftestCommand(redisClient *c) {
|
||||||
|
int j, i;
|
||||||
|
sds bitcounters = sdsnewlen(NULL,REDIS_HLL_SIZE);
|
||||||
|
uint8_t bytecounters[REDIS_HLL_REGISTERS];
|
||||||
|
|
||||||
|
for (j = 0; j < REDIS_HLL_TEST_CYCLES; j++) {
|
||||||
|
/* Set the HLL counters and an array of unsigned byes of the
|
||||||
|
* same size to the same set of random values. */
|
||||||
|
for (i = 0; i < REDIS_HLL_REGISTERS; i++) {
|
||||||
|
unsigned int r = rand() & REDIS_HLL_REGISTER_MAX;
|
||||||
|
|
||||||
|
bytecounters[i] = r;
|
||||||
|
HLL_SET_REGISTER(bitcounters,i,r);
|
||||||
|
}
|
||||||
|
/* Check that we are able to retrieve the same values. */
|
||||||
|
for (i = 0; i < REDIS_HLL_REGISTERS; i++) {
|
||||||
|
unsigned int val;
|
||||||
|
|
||||||
|
HLL_GET_REGISTER(val,bitcounters,i);
|
||||||
|
if (val != bytecounters[i]) {
|
||||||
|
addReplyErrorFormat(c,
|
||||||
|
"TESTFAILED Register %d should be %d but is %d",
|
||||||
|
i, (int) bytecounters[i], (int) val);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Success! */
|
||||||
|
addReply(c,shared.ok);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
sdsfree(bitcounters);
|
||||||
|
}
|
||||||
|
@ -267,7 +267,8 @@ struct redisCommand redisCommandTable[] = {
|
|||||||
{"bitop",bitopCommand,-4,"wm",0,NULL,2,-1,1,0,0},
|
{"bitop",bitopCommand,-4,"wm",0,NULL,2,-1,1,0,0},
|
||||||
{"bitcount",bitcountCommand,-2,"r",0,NULL,1,1,1,0,0},
|
{"bitcount",bitcountCommand,-2,"r",0,NULL,1,1,1,0,0},
|
||||||
{"bitpos",bitposCommand,-3,"r",0,NULL,1,1,1,0,0},
|
{"bitpos",bitposCommand,-3,"r",0,NULL,1,1,1,0,0},
|
||||||
{"wait",waitCommand,3,"rs",0,NULL,0,0,0,0,0}
|
{"wait",waitCommand,3,"rs",0,NULL,0,0,0,0,0},
|
||||||
|
{"hllselftest",hllSelftestCommand,1,"r",0,NULL,0,0,0,0,0},
|
||||||
};
|
};
|
||||||
|
|
||||||
struct evictionPoolEntry *evictionPoolAlloc(void);
|
struct evictionPoolEntry *evictionPoolAlloc(void);
|
||||||
|
@ -1447,6 +1447,7 @@ void bitcountCommand(redisClient *c);
|
|||||||
void bitposCommand(redisClient *c);
|
void bitposCommand(redisClient *c);
|
||||||
void replconfCommand(redisClient *c);
|
void replconfCommand(redisClient *c);
|
||||||
void waitCommand(redisClient *c);
|
void waitCommand(redisClient *c);
|
||||||
|
void hllSelftestCommand(redisClient *c);
|
||||||
|
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
void *calloc(size_t count, size_t size) __attribute__ ((deprecated));
|
void *calloc(size_t count, size_t size) __attribute__ ((deprecated));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user