use
5.010;
$Data::Dumper::Sortkeys
= 1;
say
"Please read source code to make sure you understand what this script is benchmarking"
;
sub
eq_or_die {
my
(
$got
,
$expected
,
$parser
) =
@_
;
unless
( Dumper(
$got
) eq Dumper(
$expected
) ) {
die
"Invalid result in $parser: "
. Dumper(
$got
);
}
}
my
$reply
=
join
"\r\n"
,
qw(
*3
:123
$-1
$9
hhhhhhhhh
)
,
""
;
my
$true
=
sub
{ 1 };
my
$rdb_pp
= RedisDB::Parser::PP->new;
$rdb_pp
->set_default_callback(
$true
);
my
$rdb_xs
= RedisDB::Parser::XS->new;
$rdb_xs
->set_default_callback(
$true
);
my
$rdb_parsed
= [ 123,
undef
,
'hhhhhhhhh'
];
$rdb_pp
->push_callback(
sub
{ eq_or_die(
$_
[1],
$rdb_parsed
,
"RedisDB PP"
) } );
$rdb_pp
->parse(
$reply
);
$rdb_xs
->push_callback(
sub
{ eq_or_die(
$_
[1],
$rdb_parsed
,
"RedisDB XS"
) } );
$rdb_xs
->parse(
$reply
);
my
$pr_pp
= Protocol::Redis->new(
api
=> 1 );
my
$pr_xs
= Protocol::Redis::XS->new(
api
=> 1 );
my
$pr_parsed
= {
data
=> [
{
data
=>
'123'
,
type
=>
':'
},
{
type
=>
'$'
,
data
=>
undef
},
{
type
=>
'$'
,
data
=>
'hhhhhhhhh'
}
],
type
=>
'*'
};
$pr_pp
->on_message(
sub
{ eq_or_die(
$_
[1],
$pr_parsed
,
"Protocol::Redis"
) } );
$pr_pp
->parse(
$reply
);
$pr_parsed
->{data}[0]{data} = 123;
$pr_xs
->on_message(
sub
{ eq_or_die(
$_
[1],
$pr_parsed
,
"Protocol::Redis::XS"
) } );
$pr_xs
->parse(
$reply
);
$pr_pp
->on_message(
$true
);
$pr_xs
->on_message(
$true
);
my
$parse_redis_parsed
= [
'*'
, [ [
':'
,
'123'
],
undef
,
'hhhhhhhhh'
] ];
parse_redis
$reply
, \
my
@res
;
eq_or_die
$res
[0],
$parse_redis_parsed
,
"Parse::Redis::XS"
;
sub
redis_parser {
state
$buf
=
''
;
$buf
.=
shift
;
my
$len
= parse_redis
$buf
, \
my
@res
;
substr
$buf
, 0,
$len
,
''
;
$true
->(
$_
)
for
@res
;
}
my
@replies
= (
[
"Status message"
,
"+OK\r\n"
],
[
"Bulk reply"
,
"\$3\r\nfoo\r\n"
],
[
"Multibulk reply"
,
$reply
]
);
for
(
@replies
) {
my
(
$test
,
$reply
) =
@$_
;
say
"\nParsing $test\n"
;
cmpthese - 5,
{
"RedisDB::Parser::PP"
=>
sub
{
$rdb_pp
->parse(
$reply
)
for
1 .. 10000 },
"RedisDB::Parser::XS"
=>
sub
{
$rdb_xs
->parse(
$reply
)
for
1 .. 10000 },
"Protocol::Redis"
=>
sub
{
$pr_pp
->parse(
$reply
)
for
1 .. 10000 },
"Protocol::Redis::XS"
=>
sub
{
$pr_xs
->parse(
$reply
)
for
1 .. 10000 },
"wrapped Parse::Redis::XS"
=>
sub
{ redis_parser(
$reply
)
for
1 .. 10000 },
"bare Parse::Redis::XS"
=>
sub
{ parse_redis
$reply
, \
my
@res
for
1 .. 10000 },
};
}