Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
ae7db3fe
Commit
ae7db3fe
authored
Dec 23, 2010
by
antirez
Browse files
Merge remote branch 'pietern/bench-fix' into 2.2
parents
454f4bfd
23803889
Changes
1
Hide whitespace changes
Inline
Side-by-side
src/redis-benchmark.c
View file @
ae7db3fe
...
@@ -45,10 +45,6 @@
...
@@ -45,10 +45,6 @@
#include "adlist.h"
#include "adlist.h"
#include "zmalloc.h"
#include "zmalloc.h"
#define CLIENT_CONNECTING 0
#define CLIENT_SENDQUERY 1
#define CLIENT_READREPLY 2
#define REDIS_NOTUSED(V) ((void) V)
#define REDIS_NOTUSED(V) ((void) V)
static
struct
config
{
static
struct
config
{
...
@@ -78,10 +74,10 @@ static struct config {
...
@@ -78,10 +74,10 @@ static struct config {
typedef
struct
_client
{
typedef
struct
_client
{
redisContext
*
context
;
redisContext
*
context
;
int
state
;
sds
obuf
;
sds
obuf
;
char
*
randptr
[
10
];
/* needed for MSET against 10 keys */
size_t
randlen
;
unsigned
int
written
;
/* bytes of 'obuf' already written */
unsigned
int
written
;
/* bytes of 'obuf' already written */
int
replytype
;
long
long
start
;
/* start time of a request */
long
long
start
;
/* start time of a request */
long
long
latency
;
/* request latency */
long
long
latency
;
/* request latency */
}
*
client
;
}
*
client
;
...
@@ -139,22 +135,17 @@ static void resetClient(client c) {
...
@@ -139,22 +135,17 @@ static void resetClient(client c) {
aeDeleteFileEvent
(
config
.
el
,
c
->
context
->
fd
,
AE_READABLE
);
aeDeleteFileEvent
(
config
.
el
,
c
->
context
->
fd
,
AE_READABLE
);
aeCreateFileEvent
(
config
.
el
,
c
->
context
->
fd
,
AE_WRITABLE
,
writeHandler
,
c
);
aeCreateFileEvent
(
config
.
el
,
c
->
context
->
fd
,
AE_WRITABLE
,
writeHandler
,
c
);
c
->
written
=
0
;
c
->
written
=
0
;
c
->
state
=
CLIENT_SENDQUERY
;
c
->
start
=
ustime
();
c
->
latency
=
-
1
;
}
}
static
void
randomizeClientKey
(
client
c
)
{
static
void
randomizeClientKey
(
client
c
)
{
char
*
p
;
char
buf
[
32
];
char
buf
[
32
];
long
r
;
size_t
i
,
r
;
p
=
strstr
(
c
->
obuf
,
"_rand"
);
for
(
i
=
0
;
i
<
c
->
randlen
;
i
++
)
{
if
(
!
p
)
return
;
r
=
random
()
%
config
.
randomkeys_keyspacelen
;
p
+=
5
;
snprintf
(
buf
,
sizeof
(
buf
),
"%012lu"
,
r
);
r
=
random
()
%
config
.
randomkeys_keyspacelen
;
memcpy
(
c
->
randptr
[
i
],
buf
,
12
);
sprintf
(
buf
,
"%ld"
,
r
);
}
memcpy
(
p
,
buf
,
strlen
(
buf
));
}
}
static
void
clientDone
(
client
c
)
{
static
void
clientDone
(
client
c
)
{
...
@@ -165,7 +156,6 @@ static void clientDone(client c) {
...
@@ -165,7 +156,6 @@ static void clientDone(client c) {
}
}
if
(
config
.
keepalive
)
{
if
(
config
.
keepalive
)
{
resetClient
(
c
);
resetClient
(
c
);
if
(
config
.
randomkeys
)
randomizeClientKey
(
c
);
}
else
{
}
else
{
config
.
liveclients
--
;
config
.
liveclients
--
;
createMissingClients
(
c
);
createMissingClients
(
c
);
...
@@ -195,6 +185,11 @@ static void readHandler(aeEventLoop *el, int fd, void *privdata, int mask) {
...
@@ -195,6 +185,11 @@ static void readHandler(aeEventLoop *el, int fd, void *privdata, int mask) {
exit
(
1
);
exit
(
1
);
}
}
if
(
reply
!=
NULL
)
{
if
(
reply
!=
NULL
)
{
if
(
reply
==
(
void
*
)
REDIS_REPLY_ERROR
)
{
fprintf
(
stderr
,
"Unexpected error reply, exiting...
\n
"
);
exit
(
1
);
}
if
(
config
.
donerequests
<
config
.
requests
)
if
(
config
.
donerequests
<
config
.
requests
)
config
.
latency
[
config
.
donerequests
++
]
=
c
->
latency
;
config
.
latency
[
config
.
donerequests
++
]
=
c
->
latency
;
clientDone
(
c
);
clientDone
(
c
);
...
@@ -208,11 +203,13 @@ static void writeHandler(aeEventLoop *el, int fd, void *privdata, int mask) {
...
@@ -208,11 +203,13 @@ static void writeHandler(aeEventLoop *el, int fd, void *privdata, int mask) {
REDIS_NOTUSED
(
fd
);
REDIS_NOTUSED
(
fd
);
REDIS_NOTUSED
(
mask
);
REDIS_NOTUSED
(
mask
);
if
(
c
->
state
==
CLIENT_CONNECTING
)
{
/* When nothing was written yet, randomize keys and set start time. */
c
->
state
=
CLIENT_SENDQUERY
;
if
(
c
->
written
==
0
)
{
if
(
config
.
randomkeys
)
randomizeClientKey
(
c
);
c
->
start
=
ustime
();
c
->
start
=
ustime
();
c
->
latency
=
-
1
;
c
->
latency
=
-
1
;
}
}
if
(
sdslen
(
c
->
obuf
)
>
c
->
written
)
{
if
(
sdslen
(
c
->
obuf
)
>
c
->
written
)
{
void
*
ptr
=
c
->
obuf
+
c
->
written
;
void
*
ptr
=
c
->
obuf
+
c
->
written
;
int
nwritten
=
write
(
c
->
context
->
fd
,
ptr
,
sdslen
(
c
->
obuf
)
-
c
->
written
);
int
nwritten
=
write
(
c
->
context
->
fd
,
ptr
,
sdslen
(
c
->
obuf
)
-
c
->
written
);
...
@@ -226,12 +223,11 @@ static void writeHandler(aeEventLoop *el, int fd, void *privdata, int mask) {
...
@@ -226,12 +223,11 @@ static void writeHandler(aeEventLoop *el, int fd, void *privdata, int mask) {
if
(
sdslen
(
c
->
obuf
)
==
c
->
written
)
{
if
(
sdslen
(
c
->
obuf
)
==
c
->
written
)
{
aeDeleteFileEvent
(
config
.
el
,
c
->
context
->
fd
,
AE_WRITABLE
);
aeDeleteFileEvent
(
config
.
el
,
c
->
context
->
fd
,
AE_WRITABLE
);
aeCreateFileEvent
(
config
.
el
,
c
->
context
->
fd
,
AE_READABLE
,
readHandler
,
c
);
aeCreateFileEvent
(
config
.
el
,
c
->
context
->
fd
,
AE_READABLE
,
readHandler
,
c
);
c
->
state
=
CLIENT_READREPLY
;
}
}
}
}
}
}
static
client
createClient
(
int
replytype
)
{
static
client
createClient
(
char
*
cmd
,
int
len
)
{
client
c
=
zmalloc
(
sizeof
(
struct
_client
));
client
c
=
zmalloc
(
sizeof
(
struct
_client
));
if
(
config
.
hostsocket
==
NULL
)
{
if
(
config
.
hostsocket
==
NULL
)
{
c
->
context
=
redisConnectNonBlock
(
config
.
hostip
,
config
.
hostport
);
c
->
context
=
redisConnectNonBlock
(
config
.
hostip
,
config
.
hostport
);
...
@@ -246,10 +242,22 @@ static client createClient(int replytype) {
...
@@ -246,10 +242,22 @@ static client createClient(int replytype) {
fprintf
(
stderr
,
"%s: %s
\n
"
,
config
.
hostsocket
,
c
->
context
->
errstr
);
fprintf
(
stderr
,
"%s: %s
\n
"
,
config
.
hostsocket
,
c
->
context
->
errstr
);
exit
(
1
);
exit
(
1
);
}
}
c
->
replytype
=
replytype
;
c
->
obuf
=
sdsnewlen
(
cmd
,
len
);
c
->
state
=
CLIENT_CONNECTING
;
c
->
randlen
=
0
;
c
->
obuf
=
sdsempty
();
c
->
written
=
0
;
c
->
written
=
0
;
/* Find substrings in the output buffer that need to be randomized. */
if
(
config
.
randomkeys
)
{
char
*
p
=
c
->
obuf
,
*
newline
;
while
((
p
=
strstr
(
p
,
":rand:"
))
!=
NULL
)
{
newline
=
strstr
(
p
,
"
\r\n
"
);
assert
(
newline
-
(
p
+
6
)
==
12
);
/* 12 chars for randomness */
assert
(
c
->
randlen
<
(
signed
)(
sizeof
(
c
->
randptr
)
/
sizeof
(
char
*
)));
c
->
randptr
[
c
->
randlen
++
]
=
p
+
6
;
p
=
newline
+
2
;
}
}
redisSetReplyObjectFunctions
(
c
->
context
,
NULL
);
redisSetReplyObjectFunctions
(
c
->
context
,
NULL
);
aeCreateFileEvent
(
config
.
el
,
c
->
context
->
fd
,
AE_WRITABLE
,
writeHandler
,
c
);
aeCreateFileEvent
(
config
.
el
,
c
->
context
->
fd
,
AE_WRITABLE
,
writeHandler
,
c
);
listAddNodeTail
(
config
.
clients
,
c
);
listAddNodeTail
(
config
.
clients
,
c
);
...
@@ -258,11 +266,16 @@ static client createClient(int replytype) {
...
@@ -258,11 +266,16 @@ static client createClient(int replytype) {
}
}
static
void
createMissingClients
(
client
c
)
{
static
void
createMissingClients
(
client
c
)
{
int
n
=
0
;
while
(
config
.
liveclients
<
config
.
numclients
)
{
while
(
config
.
liveclients
<
config
.
numclients
)
{
client
new
=
createClient
(
c
->
replytype
);
createClient
(
c
->
obuf
,
sdslen
(
c
->
obuf
));
sdsfree
(
new
->
obuf
);
new
->
obuf
=
sdsdup
(
c
->
obuf
);
/* Listen backlog is quite limited on most systems */
if
(
config
.
randomkeys
)
randomizeClientKey
(
c
);
if
(
++
n
>
64
)
{
usleep
(
50000
);
n
=
0
;
}
}
}
}
}
...
@@ -298,14 +311,19 @@ static void showLatencyReport(void) {
...
@@ -298,14 +311,19 @@ static void showLatencyReport(void) {
}
}
}
}
static
void
prepareForBenchmark
(
char
*
title
)
{
static
void
benchmark
(
char
*
title
,
char
*
cmd
,
int
len
)
{
client
c
;
config
.
title
=
title
;
config
.
title
=
title
;
config
.
start
=
mstime
();
config
.
donerequests
=
0
;
config
.
donerequests
=
0
;
}
static
void
endBenchmark
(
void
)
{
c
=
createClient
(
cmd
,
len
);
createMissingClients
(
c
);
config
.
start
=
mstime
();
aeMain
(
config
.
el
);
config
.
totlatency
=
mstime
()
-
config
.
start
;
config
.
totlatency
=
mstime
()
-
config
.
start
;
showLatencyReport
();
showLatencyReport
();
freeAllClients
();
freeAllClients
();
}
}
...
@@ -392,6 +410,7 @@ int showThroughput(struct aeEventLoop *eventLoop, long long id, void *clientData
...
@@ -392,6 +410,7 @@ int showThroughput(struct aeEventLoop *eventLoop, long long id, void *clientData
}
}
int
main
(
int
argc
,
char
**
argv
)
{
int
main
(
int
argc
,
char
**
argv
)
{
int
i
;
client
c
;
client
c
;
signal
(
SIGHUP
,
SIG_IGN
);
signal
(
SIGHUP
,
SIG_IGN
);
...
@@ -426,136 +445,83 @@ int main(int argc, char **argv) {
...
@@ -426,136 +445,83 @@ int main(int argc, char **argv) {
if
(
config
.
idlemode
)
{
if
(
config
.
idlemode
)
{
printf
(
"Creating %d idle connections and waiting forever (Ctrl+C when done)
\n
"
,
config
.
numclients
);
printf
(
"Creating %d idle connections and waiting forever (Ctrl+C when done)
\n
"
,
config
.
numclients
);
prepareForBenchmark
(
"IDLE"
);
c
=
createClient
(
""
,
0
);
/* will never receive a reply */
c
=
createClient
(
0
);
/* will never receive a reply */
c
->
obuf
=
sdsempty
();
createMissingClients
(
c
);
createMissingClients
(
c
);
aeMain
(
config
.
el
);
aeMain
(
config
.
el
);
/* and will wait for every */
/* and will wait for every */
}
}
do
{
do
{
prepareForBenchmark
(
"PING"
);
char
*
data
,
*
cmd
;
c
=
createClient
(
REDIS_REPLY_STATUS
);
int
len
;
c
->
obuf
=
sdscat
(
c
->
obuf
,
"PING
\r\n
"
);
createMissingClients
(
c
);
aeMain
(
config
.
el
);
endBenchmark
();
prepareForBenchmark
(
"PING (multi bulk)"
);
data
=
zmalloc
(
config
.
datasize
+
1
);
c
=
createClient
(
REDIS_REPLY_STATUS
);
memset
(
data
,
'x'
,
config
.
datasize
);
c
->
obuf
=
sdscat
(
c
->
obuf
,
"*1
\r\n
$4
\r\n
PING
\r\n
"
);
data
[
config
.
datasize
]
=
'\0'
;
createMissingClients
(
c
);
aeMain
(
config
.
el
);
benchmark
(
"PING (inline)"
,
"PING
\r\n
"
,
6
);
endBenchmark
();
len
=
redisFormatCommand
(
&
cmd
,
"PING"
);
prepareForBenchmark
(
"MSET (10 keys, multi bulk)"
);
benchmark
(
"PING"
,
cmd
,
len
);
c
=
createClient
(
REDIS_REPLY_ARRAY
);
free
(
cmd
);
c
->
obuf
=
sdscatprintf
(
c
->
obuf
,
"*%d
\r\n
$4
\r\n
MSET
\r\n
"
,
11
);
{
const
char
*
argv
[
21
];
int
i
;
argv
[
0
]
=
"MSET"
;
char
*
data
=
zmalloc
(
config
.
datasize
+
2
);
for
(
i
=
1
;
i
<
21
;
i
+=
2
)
{
memset
(
data
,
'x'
,
config
.
datasize
);
argv
[
i
]
=
"foo:rand:000000000000"
;
for
(
i
=
0
;
i
<
10
;
i
++
)
{
argv
[
i
+
1
]
=
data
;
c
->
obuf
=
sdscatprintf
(
c
->
obuf
,
"$%d
\r\n
%s
\r\n
"
,
config
.
datasize
,
data
);
}
zfree
(
data
);
}
createMissingClients
(
c
);
aeMain
(
config
.
el
);
endBenchmark
();
prepareForBenchmark
(
"SET"
);
c
=
createClient
(
REDIS_REPLY_STATUS
);
c
->
obuf
=
sdscat
(
c
->
obuf
,
"*3
\r\n
$3
\r\n
SET
\r\n
$20
\r\n
foo_rand000000000000
\r\n
"
);
{
char
*
data
=
zmalloc
(
config
.
datasize
+
2
);
memset
(
data
,
'x'
,
config
.
datasize
);
data
[
config
.
datasize
]
=
'\r'
;
data
[
config
.
datasize
+
1
]
=
'\n'
;
c
->
obuf
=
sdscatprintf
(
c
->
obuf
,
"$%d
\r\n
"
,
config
.
datasize
);
c
->
obuf
=
sdscatlen
(
c
->
obuf
,
data
,
config
.
datasize
+
2
);
}
}
createMissingClients
(
c
);
len
=
redisFormatCommandArgv
(
&
cmd
,
21
,
argv
,
NULL
);
aeMain
(
config
.
el
);
benchmark
(
"MSET (10 keys)"
,
cmd
,
len
);
endBenchmark
(
);
free
(
cmd
);
prepareForBenchmark
(
"GET"
);
len
=
redisFormatCommand
(
&
cmd
,
"SET foo:rand:000000000000 %s"
,
data
);
c
=
createClient
(
REDIS_REPLY_STRING
);
benchmark
(
"SET"
,
cmd
,
len
);
c
->
obuf
=
sdscat
(
c
->
obuf
,
"GET foo_rand000000000000
\r\n
"
);
free
(
cmd
);
createMissingClients
(
c
);
aeMain
(
config
.
el
);
endBenchmark
();
prepareForBenchmark
(
"INCR"
);
len
=
redisFormatCommand
(
&
cmd
,
"GET foo:rand:000000000000"
);
c
=
createClient
(
REDIS_REPLY_INTEGER
);
benchmark
(
"GET"
,
cmd
,
len
);
c
->
obuf
=
sdscat
(
c
->
obuf
,
"INCR counter_rand000000000000
\r\n
"
);
free
(
cmd
);
createMissingClients
(
c
);
aeMain
(
config
.
el
);
endBenchmark
();
prepareForBenchmark
(
"LPUSH"
);
len
=
redisFormatCommand
(
&
cmd
,
"INCR counter:rand:000000000000"
);
c
=
createClient
(
REDIS_REPLY_INTEGER
);
benchmark
(
"INCR"
,
cmd
,
len
);
c
->
obuf
=
sdscat
(
c
->
obuf
,
"LPUSH mylist bar
\r\n
"
);
free
(
cmd
);
createMissingClients
(
c
);
aeMain
(
config
.
el
);
endBenchmark
();
prepareForBenchmark
(
"LPOP"
);
len
=
redisFormatCommand
(
&
cmd
,
"LPUSH mylist %s"
,
data
);
c
=
createClient
(
REDIS_REPLY_STRING
);
benchmark
(
"LPUSH"
,
cmd
,
len
);
c
->
obuf
=
sdscat
(
c
->
obuf
,
"LPOP mylist
\r\n
"
);
free
(
cmd
);
createMissingClients
(
c
);
aeMain
(
config
.
el
);
endBenchmark
();
prepareForBenchmark
(
"SADD"
);
len
=
redisFormatCommand
(
&
cmd
,
"LPOP mylist"
);
c
=
createClient
(
REDIS_REPLY_STATUS
);
benchmark
(
"LPOP"
,
cmd
,
len
);
c
->
obuf
=
sdscat
(
c
->
obuf
,
"SADD myset counter_rand000000000000
\r\n
"
);
free
(
cmd
);
createMissingClients
(
c
);
aeMain
(
config
.
el
);
endBenchmark
();
prepareForBenchmark
(
"SPOP"
);
len
=
redisFormatCommand
(
&
cmd
,
"SADD myset counter:rand:000000000000"
);
c
=
createClient
(
REDIS_REPLY_STRING
);
benchmark
(
"SADD"
,
cmd
,
len
);
c
->
obuf
=
sdscat
(
c
->
obuf
,
"SPOP myset
\r\n
"
);
free
(
cmd
);
createMissingClients
(
c
);
aeMain
(
config
.
el
);
endBenchmark
();
prepareForBenchmark
(
"LPUSH (again, in order to bench LRANGE)"
);
len
=
redisFormatCommand
(
&
cmd
,
"SPOP myset"
);
c
=
createClient
(
REDIS_REPLY_STATUS
);
benchmark
(
"SPOP"
,
cmd
,
len
);
c
->
obuf
=
sdscat
(
c
->
obuf
,
"LPUSH mylist bar
\r\n
"
);
free
(
cmd
);
createMissingClients
(
c
);
aeMain
(
config
.
el
);
endBenchmark
();
prepareForBenchmark
(
"LRANGE (first 100 elements)"
);
len
=
redisFormatCommand
(
&
cmd
,
"LPUSH mylist %s"
,
data
);
c
=
createClient
(
REDIS_REPLY_ARRAY
);
benchmark
(
"LPUSH (again, in order to bench LRANGE)"
,
cmd
,
len
);
c
->
obuf
=
sdscat
(
c
->
obuf
,
"LRANGE mylist 0 99
\r\n
"
);
free
(
cmd
);
createMissingClients
(
c
);
aeMain
(
config
.
el
);
endBenchmark
();
prepareForBenchmark
(
"LRANGE (first 300 elements)"
);
len
=
redisFormatCommand
(
&
cmd
,
"LRANGE mylist 0 99"
);
c
=
createClient
(
REDIS_REPLY_ARRAY
);
benchmark
(
"LRANGE (first 100 elements)"
,
cmd
,
len
);
c
->
obuf
=
sdscat
(
c
->
obuf
,
"LRANGE mylist 0 299
\r\n
"
);
free
(
cmd
);
createMissingClients
(
c
);
aeMain
(
config
.
el
);
endBenchmark
();
prepareForBenchmark
(
"LRANGE (first 450 elements)"
);
len
=
redisFormatCommand
(
&
cmd
,
"LRANGE mylist 0 299"
);
c
=
createClient
(
REDIS_REPLY_ARRAY
);
benchmark
(
"LRANGE (first 300 elements)"
,
cmd
,
len
);
c
->
obuf
=
sdscat
(
c
->
obuf
,
"LRANGE mylist 0 449
\r\n
"
);
free
(
cmd
);
createMissingClients
(
c
);
aeMain
(
config
.
el
);
endBenchmark
();
prepareForBenchmark
(
"LRANGE (first 600 elements)"
);
len
=
redisFormatCommand
(
&
cmd
,
"LRANGE mylist 0 449"
);
c
=
createClient
(
REDIS_REPLY_ARRAY
);
benchmark
(
"LRANGE (first 450 elements)"
,
cmd
,
len
);
c
->
obuf
=
sdscat
(
c
->
obuf
,
"LRANGE mylist 0 599
\r\n
"
);
free
(
cmd
);
createMissingClients
(
c
);
aeMain
(
config
.
el
);
len
=
redisFormatCommand
(
&
cmd
,
"LRANGE mylist 0 599"
);
endBenchmark
();
benchmark
(
"LRANGE (first 600 elements)"
,
cmd
,
len
);
free
(
cmd
);
printf
(
"
\n
"
);
printf
(
"
\n
"
);
}
while
(
config
.
loop
);
}
while
(
config
.
loop
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment