in reply to Re: Re: Sending an anonymous hash to a sub
in thread Sending an anonymous hash to a sub
Be aware that doing
sub describe { my $ref = shift(); my %person = %{$ref}; print "$person{name} is a $person{job}" } ... describe( { person=>'buffy', job=>'vampire slayer' } );
You are not "passing an anonymous hash" you are
NOTE: This is far from an accurate picture, but the main inaccuracies are in the steps that I haven't expanded!
The point is that by constructing an anonymous hash from a list, passing that hash, by reference to a sub, then flattening that hash back to a list and then constructing a new hash from that list, you are doing a huge amount of work that is completely unnecessary and wasteful. It is true that perl does this in the "twinkling of an eye", but by avoiding it, it could achieve the same ends in a "twinkle of a twinkling".
If your going to use named parameters to subs, either pass a list in and construct the hash (once) at the destination.
sub describe { my %person = @_; print "$person{name} is a $person{job}" } ... describe( person=>'buffy', job=>'vampire slayer' );
Or, construct the anonymous hash in the calling program, pass a reference and use that reference to access the hash you constructed.
sub describe { my $personref = shift; print "$person->{name} is a $person->{job}"; } ... describe( { person=>'buffy', job=>'vampire slayer' } );
The way you are doing it here is just sooo wasteful. For two element hashes with short keys and one depth of call, the overhead is probably not dramatic in realtime terms. But if you use this practice for larger hashes with longer keys and going a several levels deep, it really begins to mount up.
By way of demonstration, these results from the benchmark below show the difference in using 4 different methods of passing two strings to a sub and using those parameters to contruct a string for printing.
p:\test>Bench Rate describe1 describe2 describe3 describe4 describe1 5186/s -- -28% -76% -78% describe2 7232/s 39% -- -66% -70% describe3 21387/s 312% 196% -- -11% describe4 24048/s 364% 233% 12% --
For this set of results, the sub only constructed the string and didn't actually print it. Print is a relatively expensive operation. One view is that if the sub you are calling is going to do anything substancial (like calling print), the overhead of the parameter passing and access tends to pail in to insignificance. After all those numbers above show that describe1() will process 5,186 pairs of parameters in a second or one pair every 193 microseconds. Okay, but describe4() does 24,080 in a second or 1 every 41 microseconds. but to be fair, here are the results from the same benchmark, this time actually calling print.
p:\test>Bench -P -N=-1 >log Rate describe1 describe2 describe3 describe4 describe1 4458/s -- -25% -71% -73% describe2 5907/s 32% -- -62% -65% describe3 15361/s 245% 160% -- -8% describe4 16639/s 273% 182% 8% --
As you can see, that slows thing down considerably. describe4() is now only 2 1/2 times quicker rather than 3 1/2 times quicker than describe1(). And, if the sub was doing anything more substantial, then this difference is further depleted, but it is worth thinkng about when you code your subs.
The benchmark code
#! perl -slw use strict; use Benchmark qw[ cmpthese ]; use vars qw[ $P $N ]; sub describe1 { my $ref = shift; my %person = %{ $ref }; my @__passed_to_print = "$person{person} is a $person{job}"; print @__passed_to_print if $P; } sub describe2 { my $ref = shift; my @__passed_to_print = "$ref->{person} is a $ref->{job}"; print @__passed_to_print if $P; } sub describe3 { my( $person, $job ) = @_; my @__passed_to_print = "$person is a $job"; print @__passed_to_print if $P; } use constant { PERSON=>0, JOB=>1 }; sub describe4 { my @__passed_to_print = "$_[PERSON] is a $_[JOB]"; print @__passed_to_print if $P; } cmpthese( $N || -1, { describe1 => q[ describe1( { person=>'Buffy', job=>'Vampire Slayer +' } ); ], describe2 => q[ describe2( { person=>'Buffy', job=>'Vampire Slayer +' } ); ], describe3 => q[ describe3( 'Buffy', 'Vampire Slayer +' ); ], describe4 => q[ describe4( 'Buffy', 'Vampire Slayer +' ); ], });
|
|---|