4392 Commits

Author SHA1 Message Date
Raymond Myers
21c9372454 Change HLL* to PF* in error messages 2014-04-16 15:09:45 +02:00
antirez
f307a51049 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:09:45 +02:00
antirez
08516c1ab6 HyperLogLog API prefix modified from "P" to "PF".
Using both the initials of Philippe Flajolet instead of just "P".
2014-04-16 15:09:45 +02:00
antirez
0c01e293ef Makefile.dep updated with hyperloglog.o deps. 2014-04-16 15:09:45 +02:00
antirez
e262442fd4 HyperLogLog: make API use the P prefix in honor of Philippe Flajolet. 2014-04-16 15:09:45 +02:00
antirez
8ad9123a14 HLLMERGE fixed by adding a... missing loop! 2014-04-16 15:09:45 +02:00
antirez
9cb2b5003f hll-gnuplot-graph.rb: added new filter "all". 2014-04-16 15:09:45 +02:00
antirez
07daaa6ec4 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:09:45 +02:00
antirez
691846e38d 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:09:45 +02:00
antirez
7f18689a00 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:09:45 +02:00
antirez
6672e101e8 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:09:45 +02:00
antirez
df2c02785a hll-gnuplot-graph.rb: Use |error| when filter is :max 2014-04-16 15:09:45 +02:00
antirez
dc774e1bdc Ignore txt files inside utils/hyperloglog.
Those are generated to trace graphs using gnuplot.
2014-04-16 15:09:45 +02:00
antirez
00cb4c5dee 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:09:45 +02:00
antirez
2c1b4dcd40 hll-gnuplot-graph.rb added to plot HyperLogLog error graphs. 2014-04-16 15:09:45 +02:00
antirez
7acccc7ef9 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:09:45 +02:00
antirez
8be30eca17 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:09:45 +02:00
antirez
f3aa086b6d 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:09:45 +02:00
antirez
f704678d07 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:09:45 +02:00
antirez
c1f97815ca Remove a few useless operations from hllCount() fast path. 2014-04-16 15:09:45 +02:00
antirez
c16f638dc5 HLLCOUNT 3x faster taking fast path for default params. 2014-04-16 15:09:45 +02:00
antirez
e6d57660ed Use processor base types in HLL_(GET|SET)_REGISTER.
This speedups the macros by a noticeable factor.
2014-04-16 15:09:45 +02:00
antirez
650b21fb2c HyperLogLog: use precomputed table for 2^(-M[i]). 2014-04-16 15:09:45 +02:00
antirez
6aa1b23269 hll-err.rb: speedup using pipelining. 2014-04-16 15:09:44 +02:00
antirez
a0b27c329a hll-err.rb added to test error rate of Redis HyperLogLog. 2014-04-16 15:09:44 +02:00
antirez
7d04f823e1 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:09:44 +02:00
antirez
93e5876a72 HLLCOUNT implemented. 2014-04-16 15:09:44 +02:00
antirez
bb57749a86 HLLADD implemented. 2014-04-16 15:09:44 +02:00
antirez
0faae58091 hllAdd() low level HyperLogLog "add" implemented. 2014-04-16 15:09:44 +02:00
antirez
c03e7ceaaa HyperLogLog: redefine constants using "P". 2014-04-16 15:09:44 +02:00
antirez
f4839dfb27 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:09:44 +02:00
antirez
87dd31427c Use REDIS_HLL_REGISTER_MAX when possible. 2014-04-16 15:09:44 +02:00
antirez
3610af42b2 HLL_(SET|GET)_REGISTER types fixed. 2014-04-16 15:09:44 +02:00
antirez
c7344144f4 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:09:44 +02:00
antirez
be20651435 HyperLogLog: initial sketch of registers access. 2014-04-16 15:09:44 +02:00
antirez
8c6ce3dd6a Cluster: last_vote_epoch -> lastVoteEpoch.
Use cammel case for epochs that are persisted on disk.
2014-04-16 15:09:44 +02:00
antirez
1080e272de Cluster: save/restore vars that must persist after recovery.
This fixes issue #1479.
2014-04-16 15:09:44 +02:00
antirez
47fbbd9fbc Cluster: handshake "already known" error logged to VERBOSE.
This is not really an error but something that always happens for
example when creating a new cluster, or if the sysadmin rejoins manually
a node that is already known.

Since useless logs don't help, moved to VERBOSE level.
2014-04-16 15:09:44 +02:00
antirez
6875a15858 Cluster: clusterHandleConfigEpochCollision() fixed.
New config epochs must always be obtained incrementing the currentEpoch,
that is itself guaranteed to be >= the max configEpoch currently known
to the node.
2014-04-16 15:09:44 +02:00
antirez
74fd89b321 Cluster: better logging for clusterUpdateSlotsConfigWith(). 2014-04-16 15:09:44 +02:00
antirez
cf8f72c184 Cluster: CLUSTER SETSLOT implementation comment updated.
Update the comment since the implementation details changed.
2014-04-16 15:09:44 +02:00
antirez
6837863902 Cluster: redis-trib cluster allocation more even across nodes.
redis-trib used to allocate slots not considering fractions of nodes
when computing the slots_per_node amount. So the fractional part was
carried over till the end of the allocation, where the last node
received a few more slots than any other (or a lot more if the cluster
was composed of many nodes).

The computation was changed to allocate slots more evenly when they are
not exactly divisible for the number of masters we have.
2014-04-16 15:09:44 +02:00
antirez
431573ae98 Cluster: configEpoch collisions resolution.
The slave election in Redis Cluster guarantees that slaves promoted to
masters always end with unique config epochs, however failures during
manual reshardings, software bugs and operational errors may in theory
cause two nodes to have the same configEpoch.

This commit introduces a mechanism to eventually always end with different
configEpochs if a collision ever happens.

As a (wanted) side effect, this also ensures that after a new cluster
is created, all nodes will end with a different configEpoch automatically.
2014-04-16 15:09:44 +02:00
antirez
8a3dde208d Cluster: stay within 80 cols. 2014-04-16 15:09:44 +02:00
antirez
046e691a6f Fix off by one bug in freeMemoryIfNeeded() eviction pool.
Bug found by the continuous integration test running the Redis
with valgrind:

==6245== Invalid read of size 8
==6245==    at 0x4C2DEEF: memcpy@GLIBC_2.2.5 (mc_replace_strmem.c:876)
==6245==    by 0x41F9E6: freeMemoryIfNeeded (redis.c:3010)
==6245==    by 0x41D2CC: processCommand (redis.c:2069)

memmove() size argument was accounting for an extra element, going
outside the bounds of the array.
2014-03-25 10:32:50 +01:00
antirez
74d86dc13b Test: do not complain when "leaks" can't run because process died. 2014-03-25 09:34:07 +01:00
antirez
c69c40a4ae adjustOpenFilesLimit() refactoring.
In this commit:
* Decrement steps are semantically differentiated from the reserved FDs.
  Previously both values were 32 but the meaning was different.
* Make it clear that we save setrlimit errno.
* Don't explicitly handle wrapping of 'f', but prevent it from
  happening.
* Add comments to make the function flow more readable.

This integrates PR #1630
2014-03-25 09:07:17 +01:00
Matt Stancliff
b2a02cc92d Fix potentially incorrect errno usage
errno may be reset by the previous call to redisLog, so capture
the original value for proper error reporting.
2014-03-25 09:07:17 +01:00
Matt Stancliff
01fe750c6a Add REDIS_MIN_RESERVED_FDS define for open fds
Also update the original REDIS_EVENTLOOP_FDSET_INCR to
include REDIS_MIN_RESERVED_FDS. REDIS_EVENTLOOP_FDSET_INCR
exists to make sure more than (maxclients+RESERVED) entries
are allocated, but we can only guarantee that if we include
the current value of REDIS_MIN_RESERVED_FDS as a minimum
for the INCR size.
2014-03-25 09:07:17 +01:00
Matt Stancliff
1e7b99809b Fix infinite loop on startup if ulimit too low
Fun fact: rlim_t is an unsigned long long on all platforms.

Continually subtracting from a rlim_t makes it get smaller
and smaller until it wraps, then you're up to 2^64-1.

This was causing an infinite loop on Redis startup if
your ulimit was extremely (almost comically) low.

The case of (f > oldlimit) would never be met in a case like:

    f = 150
    while (f > 20) f -= 128

Since f is unsigned, it can't go negative and would
take on values of:

    Iteration 1: 150 - 128 => 22
    Iteration 2:  22 - 128 => 18446744073709551510
    Iterations 3-∞: ...

To catch the wraparound, we use the previous value of f
stored in limit.rlimit_cur.  If we subtract from f and
get a larger number than the value it had previously,
we print an error and exit since we don't have enough
file descriptors to help the user at this point.

Thanks to @bs3g for the inspiration to fix this problem.
Patches existed from @bs3g at antirez#1227, but I needed to repair a few other
parts of Redis simultaneously, so I didn't get a chance to use them.
2014-03-25 09:07:17 +01:00