Skip to content

Commit ba54b38

Browse files
committed
Performance measurement for cached AUTOLOAD methods
1 parent 09424ad commit ba54b38

File tree

3 files changed

+136
-1
lines changed

3 files changed

+136
-1
lines changed

lib/Redis.pm

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,10 +205,27 @@ sub DESTROY { }
205205
our $AUTOLOAD;
206206

207207
sub AUTOLOAD {
208-
my $self = shift;
208+
my $self = $_[0];
209209

210210
my $command = $AUTOLOAD;
211211
$command =~ s/.*://;
212+
213+
my $method = $self->__mk_method($AUTOLOAD, $command);
214+
goto $method;
215+
}
216+
217+
sub __mk_method {
218+
my $self = shift;
219+
my $full_name = shift;
220+
my $command = shift;
221+
222+
return sub { shift->__std_cmd($command, @_) };
223+
}
224+
225+
sub __std_cmd {
226+
my $self = shift;
227+
my $command = shift;
228+
212229
$self->__is_valid_command($command);
213230

214231
## Fast path, no reconnect

lib/Redis/AutoloadCache.pm

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package Redis::AutoloadCache;
2+
3+
use strict;
4+
use warnings;
5+
6+
use base qw<Redis>;
7+
8+
sub __mk_method {
9+
my $self = shift;
10+
my $full_name = shift;
11+
my $command = shift;
12+
13+
my $method = $self->SUPER::__mk_method($full_name, $command);
14+
15+
no strict 'refs';
16+
*$full_name = $method;
17+
18+
return $method;
19+
}
20+
21+
1;

timing.pl

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
#! /usr/bin/env perl
2+
3+
use strict;
4+
use warnings;
5+
6+
use lib 't/tlib';
7+
use Test::More;
8+
use Test::SpawnRedisServer;
9+
10+
use Redis;
11+
use Redis::AutoloadCache;
12+
use Benchmark qw<cmpthese>;
13+
14+
my $TASK_SIZE = $ARGV[0] || 1e5;
15+
16+
{
17+
my ($c, $srv) = redis();
18+
END { $c->() if $c }
19+
20+
my $n = 1 + int 1000 / sqrt $TASK_SIZE;
21+
print "Benchmarking $TASK_SIZE requests $n times ...\n";
22+
cmpthese($n, {
23+
cached => sub { work('Redis::AutoloadCache', $srv) },
24+
uncached => sub { work('Redis', $srv) },
25+
});
26+
27+
print "\n";
28+
}
29+
30+
sub work {
31+
my ($class, $srv) = @_;
32+
my $redis = $class->new(server => $srv);
33+
$redis->hset('k', $_ => $_) for 1 .. $TASK_SIZE;
34+
$redis->del('k');
35+
}
36+
37+
__END__
38+
39+
=pod
40+
41+
Test platform:
42+
43+
- Perl 5.14.2, compiled 64-bit without ithreads
44+
- Redis 2.4.8, compiled 32-bit, and connecting by TCP to localhost
45+
- 2.53 GHz Intel Core 2 Duo
46+
- Mac OS 10.6.8
47+
48+
Results:
49+
50+
$ for n in 100 1000 10000 100000 200000 500000 1000000; do
51+
> perl -Ilib timing.pl $n
52+
> done
53+
Benchmarking 100 requests 101 times ...
54+
Rate uncached cached
55+
uncached 103/s -- -10%
56+
cached 115/s 11% --
57+
58+
Benchmarking 1000 requests 32 times ...
59+
Rate uncached cached
60+
uncached 10.8/s -- -11%
61+
cached 12.2/s 13% --
62+
63+
Benchmarking 10000 requests 11 times ...
64+
Rate uncached cached
65+
uncached 1.09/s -- -11%
66+
cached 1.22/s 12% --
67+
68+
Benchmarking 100000 requests 4 times ...
69+
s/iter uncached cached
70+
uncached 9.25 -- -11%
71+
cached 8.20 13% --
72+
73+
Benchmarking 200000 requests 3 times ...
74+
(warning: too few iterations for a reliable count)
75+
(warning: too few iterations for a reliable count)
76+
s/iter uncached cached
77+
uncached 18.4 -- -11%
78+
cached 16.5 12% --
79+
80+
Benchmarking 500000 requests 2 times ...
81+
(warning: too few iterations for a reliable count)
82+
(warning: too few iterations for a reliable count)
83+
s/iter uncached cached
84+
uncached 46.0 -- -11%
85+
cached 40.8 13% --
86+
87+
Benchmarking 1000000 requests 2 times ...
88+
(warning: too few iterations for a reliable count)
89+
(warning: too few iterations for a reliable count)
90+
s/iter uncached cached
91+
uncached 92.4 -- -12%
92+
cached 81.7 13% --
93+
94+
So caching AUTOLOAD methods yields a reliable speedup for this workload of
95+
between 11% and 13% compared to the uncached version. Furthermore, that
96+
speedup seems to be stable while varying $TASK_SIZE by several orders of
97+
magnitude.

0 commit comments

Comments
 (0)