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
- constructing and anonymous hash
- For each odd numbered value in your list
- For each character in that value
- Add the ascii value of that character to an accumulator and muiltiply it by its character position
- perform various shifts and ors and stuff on it
- next character
- allocate some memory
- construct an Array of Arrays
- use the hash value we just calculated to pick an element in this array
- save a copy of the value we hashed and point the key element of the array element we chose at it.
- save a copy of the next even numbered element from the list and point the VALUE element of the array element we chose at it.
- next element
- taking a reference to that anonymous hash
- constructing an alias to that reference
- expanding the size of an array (@_) by 1
- copying the alias to that new array element
- passing that array to the subroutine
- contructing a new scalar ($ref)
- copying the alias from the array into your new variable
- shrinking the array (@_) by one element
- converting the contents of the anonymous hash from earlier back to a flat list
- constructing a new hash (%person)
- For each odd numbered value in your list
- For each character in that value
- Add the ascii value of that character to an accumulator and muiltiply it by its character position
- perform various shifts and ors and stuff on it
- next character
- allocate some memory
- construct an Array of Arrays
- use the hash value we just calculated to pick an element in this array
- save a copy of the value we hashed and point the key element of the array element we chose at it.
- save a copy of the next even numbered element from the list and point the VALUE element of the array element we chose at it.
- next element
- Take the constant 'person'
- For each character in that value
- Add the ascii value of that character to an accumulator and muiltiply it by its character position
- perform various shifts and ors and stuff on it
- next character
- use the hash we just calculated as the index into the array of arrays we (re) constructed
- follow the VALUE pointer and get the string 'Buffy'
- push that onto a new array (@_) that we will pass to print
- take the constant 'job'
- For each character in that value
- Add the ascii value of that character to an accumulator and muiltiply it by its character position
- perform various shifts and ors and stuff on it
- next character
use the hash we just calculated as the index into the array of arrays we (re) constructed
follow the VALUE pointer and get the string 'Buffy'
push that onto a new array (@_) that we will pass to print
Look up the address of the function print and pass the array @_ to it.
Discard the variable $ref
Discard the hash %person
Discard the array @_ (twice)
Discard the anonymous hash
Return to the calling program.
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% --
- describe1 is the method you showed of passing an anonymous hash and then copying that to a local hash
- describe2 is the method above of passing a list and constrcuting a hash once at the destination.
- describe3 is the 'usual' method of just pasing the string in a position dependant list and assigning them to local named variables
- describe4 is doing the same thing but using the aliases $_[0] and $_1 to access them.
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
Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
If I understand your problem, I can solve it! Of course, the same can be said for you.
|