user184968
user184968

Reputation:

How to understand redis-cli's result vs redis-benchmark's result

First, I am new to Redis.

So, I measure latency with redis-cli:

$ redis-cli --latency
min: 0, max: 31, avg: 0.55 (5216 samples)^C

OK, on average I get response in 0.55 milliseconds. From this I assume that using only one connection in 1 second I can get: 1000ms / 0.55ms = 1800 requests per second.

Then on the same computer I run redis-benchmark using only one connection and get more than 6000 requests per second:

$ redis-benchmark -q -n 100000 -c 1 -P 1
PING_INLINE: 5953.80 requests per second
PING_BULK: 6189.65 requests per second

So having measured latency I expected to get around 2000 request per seconds at best. However I got 6000 request per second. I cannot find explanation for it. Am I correct when I calculate: 1000ms / 0.55ms = 1800 requests per second?

Upvotes: 4

Views: 2813

Answers (1)

Didier Spezia
Didier Spezia

Reputation: 73246

Yes, your maths are correct.

IMO, the discrepancy comes from scheduling artifacts (i.e. to the behavior of the operating system scheduler or the network loopback).

redis-cli latency is implemented by a loop which only sends a PING command before waiting for 10 ms. Let's try an experiment and compare the result of redis-cli --latency with the 10 ms wait state and without.

In order to be accurate, we first make sure the client and server are always scheduled on deterministic CPU cores. Note: it is generally a good idea to do it for benchmarking purpose on NUMA boxes. Also, make sure the frequency of the CPUs is blocked to a given value (i.e. no power mode management).

# Starting Redis
numactl -C 2 src/redis-server redis.conf
# Running benchmark
numactl -C 4 src/redis-benchmark -n 100000 -c 1 -q -P 1 -t PING
PING_INLINE: 26336.58 requests per second
PING_BULK: 27166.53 requests per second

Now let's look at the latency (with the 10 ms wait state):

numactl -C 4 src/redis-cli --latency
min: 0, max: 1, avg: 0.17761 (2376 samples)

It seems too high compared to the throughput result of redis-benchmark.

Then, we alter the source code of redis-cli.c to remove the wait state, and we recompile. The code has also been modified to display more accurate figures (but less frequently, because there is no wait state anymore).

Here is the diff against redis 3.0.5:
1123,1128c1123
<             avg = ((double) tot)/((double)count);
<         }
<         if ( count % 1024 == 0 ) {
<             printf("\x1b[0G\x1b[2Kmin: %lld, max: %lld, avg: %.5f (%lld samples)",
<                 min, max, avg, count);
<             fflush(stdout);
---
>             avg = (double) tot/count;
1129a1125,1127
>         printf("\x1b[0G\x1b[2Kmin: %lld, max: %lld, avg: %.2f (%lld samples)",
>             min, max, avg, count);
>         fflush(stdout);
1135a1134
>         usleep(LATENCY_SAMPLE_RATE * 1000);

Note that this patch should not be used against a real system, since it will make the redis-client --latency feature expensive and intrusive for the performance of the server. Its purpose is just to illustrate my point for the current discussion.

Here we go again:

numactl -C 4 src/redis-cli --latency
min: 0, max: 1, avg: 0.03605 (745280 samples)

Surprise! The average latency is now much lower. Furthermore, 1000/0.03605=27739.25, which is completely in line with the result of redis-benchmark.

Morality: the more the client loop is scheduled by the OS, the lower the average latency. It is wise to trust redis-benchmark over redis-cli --latency if your Redis clients are active enough. And anyway keep in mind the average latency does not mean much for the performance of a system (i.e. you should also look at the latency distribution, the high percentiles, etc. ..)

Upvotes: 8

Related Questions