22 Commits

Author SHA1 Message Date
antirez
be7fe2b92b HLLMERGE implemented.
Merge N HLL data structures by selecting the max value for every
M[i] register among the set of HLLs.
2014-04-16 15:23:21 +02:00
antirez
39dd1f648d HLLCOUNT is technically a write command
When we update the cached value, we need to propagate the command and
signal the key as modified for WATCH.
2014-04-16 15:23:21 +02:00
antirez
f07b1514bb HLLADD: propagate write when only variable name is given.
The following form is given:

    HLLADD myhll

No element is provided in the above case so if 'myhll' var does not
exist the result is to just create an empty HLL structure, and no update
will be performed on the registers.

In this case, the DB should still be set dirty and the command
propagated.
2014-04-16 15:23:21 +02:00
antirez
aad5959ddc HyperLogLog: use LINEARCOUNTING up to 3m.
The HyperLogLog original paper suggests using LINEARCOUNTING for
cardinalities < 2.5m, however for P=14 the median / max error
curves show that a value of '3' is the best pick for m = 16384.
2014-04-16 15:23:21 +02:00
antirez
c3df5965f3 HyperLogLog approximated cardinality caching.
The more we add elements to an HyperLogLog counter, the smaller is
the probability that we actually update some register.

From this observation it is easy to see how it is possible to use
caching of a previously computed cardinality and reuse it to serve
HLLCOUNT queries as long as no register was updated in the data
structure.

This commit does exactly this by using just additional 8 bytes for the
data structure to store a 64 bit unsigned integer value cached
cardinality. When the most significant bit of the 64 bit integer is set,
it means that the value computed is no longer usable since at least a
single register was modified and we need to recompute it at the next
call of HLLCOUNT.

The value is always stored in little endian format regardless of the
actual CPU endianess.
2014-04-16 15:23:21 +02:00
antirez
9e178afae9 String value unsharing refactored into proper function.
All the Redis functions that need to modify the string value of a key in
a destructive way (APPEND, SETBIT, SETRANGE, ...) require to make the
object unshared (if refcount > 1) and encoded in raw format (if encoding
is not already REDIS_ENCODING_RAW).

This was cut & pasted many times in multiple places of the code. This
commit puts the small logic needed into a function called
dbUnshareStringValue().
2014-04-16 15:22:56 +02:00
antirez
1c795db9d0 Use endian neutral hash function for HyperLogLog.
We need to be sure that you can save a dataset in a Redis instance,
reload it in a different architecture, and continue to count in the same
HyperLogLog structure.

So 32 and 64 bit, little or bit endian, must all guarantee to output the
same hash for the same element.
2014-04-16 15:19:40 +02:00
antirez
7f30998432 HyperLogLog internal representation modified.
The new representation is more obvious, starting from the LSB of the
first byte and using bits going to MSB, and passing to next byte as
needed.

There was also a subtle error: first two bits were unused, everything
was carried over on the right of two bits, even if it worked because of
the code requirement of always having a byte more at the end.

During the rewrite the code was made safer trying to avoid undefined
behavior due to shifting an uint8_t for more than 8 bits.
2014-04-16 15:19:40 +02:00
antirez
430d0ade75 Remove a few useless operations from hllCount() fast path. 2014-04-16 15:19:40 +02:00
antirez
83650a72a1 HLLCOUNT 3x faster taking fast path for default params. 2014-04-16 15:19:40 +02:00
antirez
3afd25ecc7 Use processor base types in HLL_(GET|SET)_REGISTER.
This speedups the macros by a noticeable factor.
2014-04-16 15:19:40 +02:00
antirez
0ffd5e4a30 HyperLogLog: use precomputed table for 2^(-M[i]). 2014-04-16 15:19:40 +02:00
antirez
42592a7faa HyperLogLog algorithm fixed in two ways.
There was an error in the computation of 2^register, and the sequence of
zeroes computed after the hashing did not included the "1".
2014-04-16 15:19:40 +02:00
antirez
3035075b2c HLLCOUNT implemented. 2014-04-16 15:19:40 +02:00
antirez
959d0f012a HLLADD implemented. 2014-04-16 15:19:33 +02:00
antirez
ac29bb2ae4 hllAdd() low level HyperLogLog "add" implemented. 2014-04-16 15:19:05 +02:00
antirez
2a91f548c4 HyperLogLog: redefine constants using "P". 2014-04-16 15:19:05 +02:00
antirez
3f159bbd44 HLL_SET_REGISTER fixed.
There was an error in the first version of the macro.
Now the HLLSELFTEST test reports success.
2014-04-16 15:19:05 +02:00
antirez
a18e880bf1 Use REDIS_HLL_REGISTER_MAX when possible. 2014-04-16 15:19:05 +02:00
antirez
00409d8742 HLL_(SET|GET)_REGISTER types fixed. 2014-04-16 15:19:05 +02:00
antirez
de3f821af6 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.
2014-04-16 15:18:57 +02:00
antirez
02d88fb201 HyperLogLog: initial sketch of registers access. 2014-04-16 15:17:26 +02:00