use Benchmark qw(cmpthese);
sub with_hash {
my ($one, $two) = @{$_[0]}{'one', 'two'};
}
sub wo_hash {
my ($one, $two) = @{{@_}}{'one', 'two'};
}
my %h = (one => undef, two => undef);
cmpthese(1000000, {
wo_hash => sub { wo_hash(one => 7, two => 9) },
with_hash => sub { with_hash({one => 7, two => 9}) },
with_consthash => sub { with_hash(\%h) },
with_consthash_mod => sub { @h{'one','two'} = (8,1); with_hash(\%h
+) },
with_consthash_modd => sub { @h{'one','two'} = (8,1); with_hash(\%
+h); @h{'one','two'}=() },
with_consthash_moddL => sub { local @h{'one','two'} = (8,1); with_
+hash(\%h);},
with_consthash_moddRA => sub { @h{'one','two'} = (8,1); my @r=with
+_hash(\%h); @h{'one','two'}=(); @r },
with_consthash_moddRS => sub { @h{'one','two'} = (8,1); my $r=with
+_hash(\%h); @h{'one','two'}=(); $r },
});
As you can see I tried to pass a completely constant hash, that looked OK, much better than foo({one => 1, two => 2}) (1002004/s vs 424628/s on my computer with Perl 5.8.8), the problem is that once I modified the values in the hash before the call the gain got much smaller (634921/s vs 424628/s). And the problem was that the values were kept in the hash between invocations ... which doesn't matter for numbers, but would matter for huge strings or for references. So I had to clear the values. undef()ing the whole hash destroyed any gain whatsoever, setting the values to undef took me to just 489237/s vs 424628/s. And that was if the called subroutine did not need to return anything!
I tried to use local() on the hash slice or assign the return value into a variable, but that just made things worse, in case the function was supposed to return a list, even worse than the normal inline hash version.
So even if perl created a hash for the subroutine just once, kept it and just modified and removed the values for each call, the speed gain would be fairly small. For a fairly high price both in memory footprint and code complexity.
The only thing that might really help would be to convert the named parameter calls into positional on compile time. The catch is that it would require that Perl knows, at the time it compiles the call, all named parameters the subroutine/method can take and the order in which they are expected while converted to positional. Which is completely out of question for methods.
I'm afraid we have to live with the overhead and in the rare case it actually matters, change the subroutine/method to use positional params.
|