Commit Graph

3672 Commits

Author SHA1 Message Date
ed96e115d0 HyperLogLog sparse representation slightly modified.
After running a few simulations with different alternative encodings,
it was found that the VAL opcode performs better using 5 bits for the
value and 2 bits for the run length, at least for cardinalities in the
range of interest.
2014-04-16 15:26:27 +02:00
93c75f1bf4 HyperLogLog sparse representation description and macros. 2014-04-16 15:26:26 +02:00
2b1385b9ec Add casting to match printf format.
adjustOpenFilesLimit() and clusterUpdateSlotsWithConfig() that were
assuming uint64_t is the same as unsigned long long, which is true
probably for all the systems out there that we target, but still GCC
emitted a warning since technically they are two different types.
2014-04-16 15:26:22 +02:00
12d1d18b59 ZRANGEBYLEX and ZREVRANGEBYLEX implementation. 2014-04-16 15:26:09 +02:00
a10bfded15 PFCOUNT: always unshare/decode the object.
This will be a non-op most of the times since the object will be
unshared / decoded, however it is more technically correct to start this
way since the object may be decoded even in the read-only code path.
2014-04-16 15:26:09 +02:00
ee764b0f8d Changed HyperLogLog hash seed to a non-zero value.
Using a seed of zero has the side effect of having the empty string
hashing to what is a very special case in the context of HyperLogLog: a
very long run of zeroes.

This did not influenced the correctness of the result with 16k registers
because of the harmonic mean, but still it is inconvenient that a so
obvious value maps to a so special hash.

The seed 0xadc83b19 is used instead, which is the first 64 bits of the
SHA1 of the empty string.

Reference: issue #1657.
2014-04-16 15:26:09 +02:00
091f5677a0 Initial HyperLogLog tests. 2014-04-16 15:26:09 +02:00
a97675923d Return "WRONGTYPE" error on PF* type mismatch. 2014-04-16 15:26:09 +02:00
faa7f259cc Fix PFADD infinite loop.
We need to guarantee that the last bit is 1, otherwise an element may
hash to just zeroes with probability 1/(2^64) and trigger an infinite
loop.

See issue #1657.
2014-04-16 15:26:09 +02:00
8ae6887091 Make hll-gnuplot-graph.rb callable from cli. 2014-04-16 15:26:09 +02:00
bdd8701c60 Remove HyperLogLog type checking duplicated code. 2014-04-16 15:26:09 +02:00
b3baa51403 PFGETREG added for testing purposes.
The new command allows to get a dump of the registers stored
into an HyperLogLog data structure for testing / debugging purposes.
2014-04-16 15:26:09 +02:00
348d5ea246 PFCOUNT: unshare the object when cached cardinality is modified. 2014-04-16 15:26:09 +02:00
ba0dc0be2c PFSELFTEST improved to test the approximation error. 2014-04-16 15:26:09 +02:00
c2cd48718d hll-gnuplot-graph.rb improved with new filter.
The function to generate graphs is also more flexible as now includes
step and max value. The step of the samples generation function is no
longer limited to min step of 1000.
2014-04-16 15:26:09 +02:00
ff551fad24 HyperLogLog: added magic / version.
This will allow future changes like compressed representations.
Currently the magic is not checked for performance reasons but this may
change in the future, for example if we add new types encoded in strings
that may have the same size of HyperLogLogs.
2014-04-16 15:26:09 +02:00
e08100a9ba Fixed pfadd/pfcount commands emitting hll* events instead of pf* events 2014-04-16 15:26:09 +02:00
23acae6e1c Change HLL* to PF* in error messages 2014-04-16 15:26:09 +02:00
e3773b0a0e Include redis.h before other stuff in hyperloglog.c.
Otherwise fmacros.h is included later and this may break compilation on
different systems.
2014-04-16 15:26:09 +02:00
badf23f57b HyperLogLog API prefix modified from "P" to "PF".
Using both the initials of Philippe Flajolet instead of just "P".
2014-04-16 15:26:03 +02:00
6e71459c73 Makefile.dep updated with hyperloglog.o deps. 2014-04-16 15:25:28 +02:00
2ee2bec2d6 HyperLogLog: make API use the P prefix in honor of Philippe Flajolet. 2014-04-16 15:24:15 +02:00
1e90c0066c HLLMERGE fixed by adding a... missing loop! 2014-04-16 15:23:21 +02:00
be7eef911b hll-gnuplot-graph.rb: added new filter "all". 2014-04-16 15:23:21 +02:00
f2e707b679 HyperLogLog apply bias correction using a polynomial.
Better results can be achieved by compensating for the bias of the raw
approximation just after 2.5m (when LINEARCOUNTING is no longer used) by
using a polynomial that approximates the bias at a given cardinality.

The curve used was found using this web page:

    http://www.xuru.org/rt/PR.asp

That performs polynomial regression given a set of values.
2014-04-16 15:23:21 +02:00
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
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
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
32e9996846 hll-gnuplot-graph.rb: Use |error| when filter is :max 2014-04-16 15:23:21 +02:00
9faa80ee8c Ignore txt files inside utils/hyperloglog.
Those are generated to trace graphs using gnuplot.
2014-04-16 15:23:21 +02:00
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
d6ce659ffd hll-gnuplot-graph.rb added to plot HyperLogLog error graphs. 2014-04-16 15:23:21 +02:00
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
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
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
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
430d0ade75 Remove a few useless operations from hllCount() fast path. 2014-04-16 15:19:40 +02:00
83650a72a1 HLLCOUNT 3x faster taking fast path for default params. 2014-04-16 15:19:40 +02:00
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
0ffd5e4a30 HyperLogLog: use precomputed table for 2^(-M[i]). 2014-04-16 15:19:40 +02:00
ca6973d3b6 hll-err.rb: speedup using pipelining. 2014-04-16 15:19:40 +02:00
2500f2a334 hll-err.rb added to test error rate of Redis HyperLogLog. 2014-04-16 15:19:40 +02:00
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
3035075b2c HLLCOUNT implemented. 2014-04-16 15:19:40 +02:00
959d0f012a HLLADD implemented. 2014-04-16 15:19:33 +02:00
ac29bb2ae4 hllAdd() low level HyperLogLog "add" implemented. 2014-04-16 15:19:05 +02:00
2a91f548c4 HyperLogLog: redefine constants using "P". 2014-04-16 15:19:05 +02:00
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
a18e880bf1 Use REDIS_HLL_REGISTER_MAX when possible. 2014-04-16 15:19:05 +02:00
00409d8742 HLL_(SET|GET)_REGISTER types fixed. 2014-04-16 15:19:05 +02:00