Yes, it is most definitely a micro-optimisation. This is consistent with the last two paras in my original post, although I did not explicitly use that term there.
| [reply] [Watch: Dir/Any] |
Most of the above thread is, err, basically wrong! The two Concise outputs show that the only two ops executed in each case are the GV (to get the glob containing the global hash variable) followed by a MULTIDEREF op. The ex-helem and ex-exists are ops that were optimised away and replaced with the MULTIDEREF op (on perl 5.22.0 and later, anyway) - they are no longer on the execution path.
The difference in performance between exists and a plain hash lookup is negligible, although exists should be slightly faster. The slowdown being seen is due to assigning a boolean return value to a scalar. Perl's boolean values (as returned by exists etc) are multi-valued scalars containing an int value of 0/1, a floating value of 0.0/1.0 and a string value of ""/"1". If this value is assigned to a scalar, all three parts need to be copied, including the string. Boolean values are optimised for use in conditionals. If you replace the assignment with something like
$xx_global = exists $hash{$key2} ? 1 : 2
you'll see exists becomes faster than a hash lookup.
Dave.
| [reply] [Watch: Dir/Any] [d/l] |
so the ->#NUMBER at the end of the lines are GOTOs and the - labels indicate ignored op-codes?
2 <;> nextstate(main 74 -e:1) v:%,{,469764096 ->3
- <1> ex-exists vK/1 ->4
3 <+> multideref($h{"a"}) vK/EXISTS ->4
| [reply] [Watch: Dir/Any] [d/l] [select] |
Thanks for the comments and clarifications.
If I update the benchmark code to use the ternary operator, and only a global assignment, then the general pattern remains on windows, but less so on linux.
Is anyone able to replicate these results?
I ran the above code on both a linux box (perlbrew 5.30.0, CentOS 7) and a windows laptop (windows 10, Strawberry perl 5.30.0). Each was repeated four times. (In previous posts I used Strawberry 5.28.0, but the windows machine is the same).
The relative differences on the linux machine are very small and the order changes between runs. One of the value calls is fastest across each of the runs, but not by much in absolute terms, and the exists call is second fastest for three of the four calls. On windows the value calls are always faster than the exists calls and the relative differences are much greater.
Linux results:
Windows results:
And I should reiterate my point from the original post that the relative differences remain very small. If the difference is real, then one would have to be running a very large number of calls for the choice of idiom to make any meaningful difference.
Addendum:
After writing the above, I decided to run more replications on Windows to get a better sense of how consistent the results are on my machine, and get the results below for 30 replications. I could have simplified the benchmarks to one of each type, but have left the code as-is for simplicity.
Of the 30 reps, 23 show both value calls being faster than either exists call. In only one case was exists fastest.
| [reply] [Watch: Dir/Any] [d/l] [select] |