Commit Graph

99 Commits

Author SHA1 Message Date
antirez
f50e658455 SDIFF is now able to select between two algorithms for speed.
SDIFF used an algorithm that was O(N) where N is the total number
of elements of all the sets involved in the operation.

The algorithm worked like that:

ALGORITHM 1:

1) For the first set, add all the members to an auxiliary set.
2) For all the other sets, remove all the members of the set from the
auxiliary set.

So it is an O(N) algorithm where N is the total number of elements in
all the sets involved in the diff operation.

Cristobal Viedma suggested to modify the algorithm to the following:

ALGORITHM 2:

1) Iterate all the elements of the first set.
2) For every element, check if the element also exists in all the other
remaining sets.
3) Add the element to the auxiliary set only if it does not exist in any
of the other sets.

The complexity of this algorithm on the worst case is O(N*M) where N is
the size of the first set and M the total number of sets involved in the
operation.

However when there are elements in common, with this algorithm we stop
the computation for a given element as long as we find a duplicated
element into another set.

I (antirez) added an additional step to algorithm 2 to make it faster,
that is to sort the set to subtract from the biggest to the
smallest, so that it is more likely to find a duplicate in a larger sets
that are checked before the smaller ones.

WHAT IS BETTER?

None of course, for instance if the first set is much larger than the
other sets the second algorithm does a lot more work compared to the
first algorithm.

Similarly if the first set is much smaller than the other sets, the
original algorithm will less work.

So this commit makes Redis able to guess the number of operations
required by each algorithm, and select the best at runtime according
to the input received.

However, since the second algorithm has better constant times and can do
less work if there are duplicated elements, an advantage is given to the
second algorithm.
2012-11-30 16:36:42 +01:00
antirez
395d663d29 SDIFF fuzz test added. 2012-11-30 01:35:34 +01:00
antirez
c4b0b6854e Type mismatch errors are now prefixed with WRONGTYPE.
So instead to reply with a generic error like:

-ERR ... wrong kind of value ...

now it replies with:

-WRONGTYPE ... wrong kind of value ...

This makes this particular error easy to check without resorting to
(fragile) pattern matching of the error string (however the error string
used to be consistent already).

Client libraries should return a specific exeption type for this error.

Most of the commit is about fixing unit tests.
2012-11-06 20:25:34 +01:00
antirez
0ee3f05518 Test for SRANDMEMBER with <count>. 2012-09-21 11:55:36 +02:00
antirez
7eb850ef0e A reimplementation of blocking operation internals.
Redis provides support for blocking operations such as BLPOP or BRPOP.
This operations are identical to normal LPOP and RPOP operations as long
as there are elements in the target list, but if the list is empty they
block waiting for new data to arrive to the list.

All the clients blocked waiting for th same list are served in a FIFO
way, so the first that blocked is the first to be served when there is
more data pushed by another client into the list.

The previous implementation of blocking operations was conceived to
serve clients in the context of push operations. For for instance:

1) There is a client "A" blocked on list "foo".
2) The client "B" performs `LPUSH foo somevalue`.
3) The client "A" is served in the context of the "B" LPUSH,
synchronously.

Processing things in a synchronous way was useful as if "A" pushes a
value that is served by "B", from the point of view of the database is a
NOP (no operation) thing, that is, nothing is replicated, nothing is
written in the AOF file, and so forth.

However later we implemented two things:

1) Variadic LPUSH that could add multiple values to a list in the
context of a single call.
2) BRPOPLPUSH that was a version of BRPOP that also provided a "PUSH"
side effect when receiving data.

This forced us to make the synchronous implementation more complex. If
client "B" is waiting for data, and "A" pushes three elemnents in a
single call, we needed to propagate an LPUSH with a missing argument
in the AOF and replication link. We also needed to make sure to
replicate the LPUSH side of BRPOPLPUSH, but only if in turn did not
happened to serve another blocking client into another list ;)

This were complex but with a few of mutually recursive functions
everything worked as expected... until one day we introduced scripting
in Redis.

Scripting + synchronous blocking operations = Issue #614.

Basically you can't "rewrite" a script to have just a partial effect on
the replicas and AOF file if the script happened to serve a few blocked
clients.

The solution to all this problems, implemented by this commit, is to
change the way we serve blocked clients. Instead of serving the blocked
clients synchronously, in the context of the command performing the PUSH
operation, it is now an asynchronous and iterative process:

1) If a key that has clients blocked waiting for data is the subject of
a list push operation, We simply mark keys as "ready" and put it into a
queue.
2) Every command pushing stuff on lists, as a variadic LPUSH, a script,
or whatever it is, is replicated verbatim without any rewriting.
3) Every time a Redis command, a MULTI/EXEC block, or a script,
completed its execution, we run the list of keys ready to serve blocked
clients (as more data arrived), and process this list serving the
blocked clients.
4) As a result of "3" maybe more keys are ready again for other clients
(as a result of BRPOPLPUSH we may have push operations), so we iterate
back to step "3" if it's needed.

The new code has a much simpler semantics, and a simpler to understand
implementation, with the disadvantage of not being able to "optmize out"
a PUSH+BPOP as a No OP.

This commit will be tested with care before the final merge, more tests
will be added likely.
2012-09-17 10:26:46 +02:00
antirez
84d9ef4f31 Added a new hash fuzzy tester.
The new fuzzy tester also removes elements from the hash instead of just
adding random fields. This should increase the probability to find bugs
in the implementations of the hash type internal representations.
2012-06-12 15:21:54 +02:00
antirez
c0de45924c New test: hash ziplist -> hashtable encoding conversion.
A new stress test was added to stress test the code converting a ziplist
into an hash table.

In this commit also randomValue helper function was modified to also
return negative values.
2012-06-11 15:19:46 +02:00
antirez
348ee1a40a Fixed issue #516 (ZINTERSTORE mixing sets and zsets).
Weeks ago trying to fix an harmless GCC warning I introduced a bug in
the ziplist-encoded implementations of sorted sets.

The bug completely broke zuiNext() iterator, that is used in the
ZINTERSTORE and ZUNIONSTORE implementation, so those two commands are no
longer reliable starting from Redis version 2.4.12 and latest 2.6.0-RC
releases.

This commit fixes the problem and adds a regression test.
2012-05-23 11:12:43 +02:00
antirez
c4a4755286 Ziplist encoding now tested with negative integers as well. 2012-04-23 17:27:46 +02:00
antirez
cddfd67ed4 Test SDIFF with first set empty. 2012-04-18 18:13:31 +02:00
antirez
4264459141 Test SINTER against same integer elements, but different set encoding. 2012-04-18 18:10:48 +02:00
antirez
f800942f64 Test SINTER with non existing key. 2012-04-18 18:05:02 +02:00
antirez
88f77a2b7e Added an SMOVE test where src and dest key are the same. 2012-04-18 18:00:12 +02:00
antirez
e51a218aaa New hash fuzzing test. 2012-04-18 17:56:17 +02:00
antirez
79daddd5ba Explicit RPOP/LPOP tests. 2012-04-18 17:32:48 +02:00
antirez
7aa0dfd014 Test LINSERT syntax error. 2012-04-18 17:22:14 +02:00
antirez
94e5c1d7e5 Test LINDEX out of range index. 2012-04-18 17:17:53 +02:00
antirez
8562798308 Merge conflicts resolved. 2012-03-09 22:07:45 +01:00
antirez
d347348109 Issue #330 regression test. 2012-02-16 16:13:40 +01:00
Pieter Noordhuis
ebd85e9a45 Encode small hashes with a ziplist 2012-01-02 22:14:10 -08:00
antirez
9678c37577 Added regression test for ZUNIONSTORE creating NaN (github issue #264) 2011-12-23 09:34:06 +01:00
antirez
bf758397a1 more valgrind (and other archs) friendly testing of floating number related features. 2011-11-16 14:40:50 +01:00
antirez
cd4aba36cd valgrind handles floating point numbers differently for some reason, so using "simpler" numbers to make tests happy. 2011-11-16 13:35:22 +01:00
antirez
3c5680ed9d HINCRBYFLOAT tests 2011-11-15 15:26:10 +01:00
antirez
d93f9a8644 string to number API is now more strict not accepting spaces before or after the number. A few tests converted to match the new error messages using the word float instead of double. 2011-11-14 15:34:44 +01:00
antirez
7551e23716 regression test for bug 593 added 2011-09-12 10:53:49 +02:00
Pieter Noordhuis
2d7162bb1d HDEL: Abort deleting fields when hash is removed 2011-07-27 12:29:40 +02:00
antirez
0717e3aa16 fix a test timing issue when running the test over valgrind 2011-07-11 15:44:38 +02:00
antirez
30cf7be60c the test runs less iterations of slow tests if no --accurate is given. 2011-07-11 12:15:35 +02:00
antirez
6209797d37 list test further split into smaller units 2011-07-11 11:41:23 +02:00
antirez
e46f78bd26 list test split into smaller parts 2011-07-11 11:30:46 +02:00
antirez
c1c9d551da Fix for bug 561 and other related problems 2011-06-20 17:19:36 +02:00
antirez
b002546bb4 ZREM tests 2011-05-31 20:30:54 +02:00
antirez
3738ff5f32 Fix for the variadic version of SREM. Regression test added. 2011-05-31 20:14:29 +02:00
antirez
faa2a80f89 disabled development test entry, tests moved in the right place 2011-05-31 18:49:12 +02:00
antirez
521ddcce14 Fix for ZUNIONSTORE bug when there is an empty set among input sets. Regression test added. 2011-05-19 17:58:52 +02:00
antirez
af9aed25e4 ZINTERSTORE regressiont test with two sets, intset+hashtable 2011-05-12 20:20:40 +02:00
antirez
b3a96d454e Variadic SREM 2011-04-19 17:37:03 +02:00
antirez
64a13a36e6 variadic HDEL with tests 2011-04-19 17:07:55 +02:00
antirez
271f087842 Variadic SADD tests 2011-04-15 18:28:25 +02:00
antirez
9d0a8656c1 tests for variadic list push 2011-04-15 16:52:07 +02:00
Pieter Noordhuis
100ed062c0 Test for ENCODING_SKIPLIST instead of ENCODING_RAW 2011-04-06 16:17:07 +02:00
Pieter Noordhuis
04a10b1a6d Test that sorted sets are removed when empty 2011-03-22 09:28:45 +01:00
Pieter Noordhuis
9ec4ea20a7 Test both sorted set encodings for every test 2011-03-14 10:54:37 +01:00
Pieter Noordhuis
e53ca04b50 Test for empty inner range when looking for elements in range 2011-03-11 18:18:02 +01:00
Pieter Noordhuis
8e1b327706 Test for ranges where min > max 2011-03-08 10:57:39 +01:00
Pieter Noordhuis
22b9bf1594 Move logic concerned with zset ranges
This also optimizes ZREVRANGEBYSCORE for pathological cases where a
sorted set contains many elements with the same score. Previously,
it would traverse the list from back to front in such a case.
2011-03-08 10:57:24 +01:00
Pieter Noordhuis
ecf9401415 Fix case and indent 2010-12-06 16:04:42 +01:00
Pieter Noordhuis
8a88c368ed Check other blocked clients when value could not be pushed 2010-12-06 16:04:10 +01:00
Michel Martens & Damian Janowski
baa14ef913 Fix BRPOPLPUSH behavior for all use cases. 2010-11-29 23:52:07 -03:00