If performance is an issue, you might consider eliminating the lookup function call overhead
(and the arguments about whether your module should use state or our or lexically scoped my ;-)
simply by not writing a function at all!
Instead performing your hash lookups directly.
To test this idea, I wrote the following little benchmark:
use strict;
use warnings;
use Benchmark qw(timethese);
# Test hash
my %junksites = (
'bollyinside.com' => 1,
'www.bollyinside.com' => 1,
'worldtrademarkreview.com' => 1,
'www.worldtrademarkreview.com' => 1,
);
sub KnownJunkSite {
my $val = shift;
return $junksites{$val};
}
my @testlist = ( 'bollyinside.com', 'www.bollyinside.com', 'fred', 'ww
+w.worldtrademarkreview.com' ) x 1000;
sub fn_lookup {
for my $v (@testlist) {
my $t = KnownJunkSite($v);
}
}
sub hash_lookup {
for my $v (@testlist) {
my $t = $junksites{$v};
}
}
my $href = \%junksites;
sub hashref_lookup {
for my $v (@testlist) {
my $t = $href->{$v};
}
}
timethese 50_000, {
Fn => sub { fn_lookup() },
Hash => sub { hash_lookup() },
HashRef => sub { hashref_lookup() },
};
Running the little benchmark program above on my laptop displayed:
Benchmark: timing 50000 iterations of Fn, Hash, HashRef...
Fn: 28 wallclock secs (27.56 usr + 0.00 sys = 27.56 CPU) @ 181
+4.03/s
Hash: 11 wallclock secs (11.62 usr + 0.00 sys = 11.62 CPU) @ 430
+1.08/s
HashRef: 12 wallclock secs (12.02 usr + 0.00 sys = 12.02 CPU) @ 416
+1.12/s
Note that in the sample code above, to make a direct hash lookup more pleasing to the eye, I eliminated the call to exists simply
by ensuring all keys have the true value 1.
No surprise that using the hash directly is a lot faster than calling a function
every time you do a lookup.
Also of interest is that a hash lookup is only marginally faster than a hash_ref lookup.
Based on this benchmark, rather than agonizing over whether your function should use block lexical scope
or the Perl 5.10 state feature or an our variable,
you might instead choose not to use a function at all!
That is, perform the lookup directly via a hash, rather than a function call.
Note that using a hashref, rather than a hash, gives you the
flexibility to call your code with many different hashes,
at a miniscule performance cost.
|