Hello, my hearties! Support the Pirate Party! Aarhhh, matey! P-) <-- (smiley wearing an eye patch)
I ran some benchmarks with the following code to see if elsif chains were faster than a dispatch table. I pray for your wisdom as to why a chain of elsifs which should be O(N) is faster than a hash operation which ought to be O(1). Is there some Perl Magick going on here?
#!/usr/bin/perl
# elsifbench - which is faster, a chain of elsif or a dispatch table?
# SSF 112208 042609
use strict;
use Benchmark qw/:all/;
sub random { int rand shift }
my @letters=('A'..'Z','a'..'z','0'..'9');
my $nLetters=scalar @letters;
sub elsifchain {
my $x=$letters[random($nLetters)];
my $y='xyzzy!' x random(1000);
if ($x eq 'A') {
split(/!/,$y);
}
elsif ($x eq 'B') {
split(/!/,$y);
}
elsif ($x eq 'C') {
split(/!/,$y);
}
elsif ($x eq 'D') {
split(/!/,$y);
}
elsif ($x eq 'E') {
split(/!/,$y);
}
elsif ($x eq 'F') {
split(/!/,$y);
}
elsif ($x eq 'G') {
split(/!/,$y);
}
elsif ($x eq 'H') {
split(/!/,$y);
}
elsif ($x eq 'I') {
split(/!/,$y);
}
elsif ($x eq 'J') {
split(/!/,$y);
}
elsif ($x eq 'K') {
split(/!/,$y);
}
elsif ($x eq 'L') {
split(/!/,$y);
}
elsif ($x eq 'M') {
split(/!/,$y);
}
elsif ($x eq 'N') {
split(/!/,$y);
}
elsif ($x eq 'O') {
split(/!/,$y);
}
elsif ($x eq 'P') {
split(/!/,$y);
}
elsif ($x eq 'Q') {
split(/!/,$y);
}
elsif ($x eq 'R') {
split(/!/,$y);
}
elsif ($x eq 'S') {
split(/!/,$y);
}
elsif ($x eq 'T') {
split(/!/,$y);
}
elsif ($x eq 'U') {
split(/!/,$y);
}
elsif ($x eq 'V') {
split(/!/,$y);
}
elsif ($x eq 'W') {
split(/!/,$y);
}
elsif ($x eq 'X') {
split(/!/,$y);
}
elsif ($x eq 'Y') {
split(/!/,$y);
}
elsif ($x eq 'Z') {
split(/!/,$y);
}
elsif ($x eq 'a') {
split(/!/,$y);
}
elsif ($x eq 'b') {
split(/!/,$y);
}
elsif ($x eq 'c') {
split(/!/,$y);
}
elsif ($x eq 'd') {
split(/!/,$y);
}
elsif ($x eq 'e') {
split(/!/,$y);
}
elsif ($x eq 'f') {
split(/!/,$y);
}
elsif ($x eq 'g') {
split(/!/,$y);
}
elsif ($x eq 'h') {
split(/!/,$y);
}
elsif ($x eq 'i') {
split(/!/,$y);
}
elsif ($x eq 'j') {
split(/!/,$y);
}
elsif ($x eq 'k') {
split(/!/,$y);
}
elsif ($x eq 'l') {
split(/!/,$y);
}
elsif ($x eq 'm') {
split(/!/,$y);
}
elsif ($x eq 'n') {
split(/!/,$y);
}
elsif ($x eq 'o') {
split(/!/,$y);
}
elsif ($x eq 'p') {
split(/!/,$y);
}
elsif ($x eq 'q') {
split(/!/,$y);
}
elsif ($x eq 'r') {
split(/!/,$y);
}
elsif ($x eq 's') {
split(/!/,$y);
}
elsif ($x eq 't') {
split(/!/,$y);
}
elsif ($x eq 'u') {
split(/!/,$y);
}
elsif ($x eq 'v') {
split(/!/,$y);
}
elsif ($x eq 'w') {
split(/!/,$y);
}
elsif ($x eq 'x') {
split(/!/,$y);
}
elsif ($x eq 'y') {
split(/!/,$y);
}
elsif ($x eq 'z') {
split(/!/,$y);
}
elsif ($x eq '0') {
split(/!/,$y);
}
elsif ($x eq '1') {
split(/!/,$y);
}
elsif ($x eq '2') {
split(/!/,$y);
}
elsif ($x eq '3') {
split(/!/,$y);
}
elsif ($x eq '4') {
split(/!/,$y);
}
elsif ($x eq '5') {
split(/!/,$y);
}
elsif ($x eq '6') {
split(/!/,$y);
}
elsif ($x eq '7') {
split(/!/,$y);
}
elsif ($x eq '8') {
split(/!/,$y);
}
elsif ($x eq '9') {
split(/!/,$y);
}
else {
warn "Huh?";
}
}
sub dispatch {
my $x=$letters[random($nLetters)];
my $y='xyzzy!' x random(1000);
my %dispatch=(
A=>sub { split(/!/,$y); },
B=>sub { split(/!/,$y); },
C=>sub { split(/!/,$y); },
D=>sub { split(/!/,$y); },
E=>sub { split(/!/,$y); },
F=>sub { split(/!/,$y); },
G=>sub { split(/!/,$y); },
H=>sub { split(/!/,$y); },
I=>sub { split(/!/,$y); },
J=>sub { split(/!/,$y); },
K=>sub { split(/!/,$y); },
L=>sub { split(/!/,$y); },
M=>sub { split(/!/,$y); },
N=>sub { split(/!/,$y); },
O=>sub { split(/!/,$y); },
P=>sub { split(/!/,$y); },
Q=>sub { split(/!/,$y); },
R=>sub { split(/!/,$y); },
S=>sub { split(/!/,$y); },
T=>sub { split(/!/,$y); },
U=>sub { split(/!/,$y); },
V=>sub { split(/!/,$y); },
W=>sub { split(/!/,$y); },
X=>sub { split(/!/,$y); },
Y=>sub { split(/!/,$y); },
Z=>sub { split(/!/,$y); },
a=>sub { split(/!/,$y); },
b=>sub { split(/!/,$y); },
c=>sub { split(/!/,$y); },
d=>sub { split(/!/,$y); },
e=>sub { split(/!/,$y); },
f=>sub { split(/!/,$y); },
g=>sub { split(/!/,$y); },
h=>sub { split(/!/,$y); },
i=>sub { split(/!/,$y); },
j=>sub { split(/!/,$y); },
k=>sub { split(/!/,$y); },
l=>sub { split(/!/,$y); },
m=>sub { split(/!/,$y); },
n=>sub { split(/!/,$y); },
o=>sub { split(/!/,$y); },
p=>sub { split(/!/,$y); },
q=>sub { split(/!/,$y); },
r=>sub { split(/!/,$y); },
s=>sub { split(/!/,$y); },
t=>sub { split(/!/,$y); },
u=>sub { split(/!/,$y); },
v=>sub { split(/!/,$y); },
w=>sub { split(/!/,$y); },
x=>sub { split(/!/,$y); },
y=>sub { split(/!/,$y); },
z=>sub { split(/!/,$y); },
0=>sub { split(/!/,$y); },
1=>sub { split(/!/,$y); },
2=>sub { split(/!/,$y); },
3=>sub { split(/!/,$y); },
4=>sub { split(/!/,$y); },
5=>sub { split(/!/,$y); },
6=>sub { split(/!/,$y); },
7=>sub { split(/!/,$y); },
8=>sub { split(/!/,$y); },
9=>sub { split(/!/,$y); }
);
if (exists $dispatch{$x}) {
$dispatch{$x}->();
} else {
warn "Huh?";
}
}
cmpthese(100000,{elsif=>\&elsifchain,dispatch=>\&dispatch});
exit;
__END__
A..Z = 26 items
Benchmark: timing 100000 iterations of dispatch, elsif...
dispatch: 56 wallclock secs (55.97 usr + 0.03 sys = 56.00 CPU) @ 17
+85.71/s (n=100000)
elsif: 35 wallclock secs (35.02 usr + 0.00 sys = 35.02 CPU) @ 28
+55.51/s (n=100000)
Rate dispatch elsif
dispatch 1786/s -- -37%
elsif 2856/s 60% --
A..Z, a..z, 0..9 = 62 items
Benchmark: timing 100000 iterations of dispatch, elsif...
dispatch: 93 wallclock secs (91.94 usr + 0.01 sys = 91.95 CPU) @ 10
+87.55/s (n=100000)
elsif: 41 wallclock secs (35.22 usr + 0.01 sys = 35.23 CPU) @ 28
+38.49/s (n=100000)
Rate dispatch elsif
dispatch 1088/s -- -62%
elsif 2838/s 161% --