"... keys ... isn't guaranteed to return a constant value so your function couldn't be inlined."
I disagree with that in part. I did take into consideration this from the keys doco:
"Hash entries are returned in an apparently random order."
Along with this, a couple of sentences later:
"So long as a given hash is unmodified you may rely on keys, values and each to repeatedly return the same order as each other. "
A very quick and dirty test (which I ran a number of times) with
$ perl -e 'my %x = qw{@ 1 | 2}; for (1..30) { print keys %x }; print " +\n"'
always returned one of these two:
|@|@|@|@|@|@|@|@|@|@|@|@|@|@|@|@|@|@|@|@|@|@|@|@|@|@|@|@|@|@ @|@|@|@|@|@|@|@|@|@|@|@|@|@|@|@|@|@|@|@|@|@|@|@|@|@|@|@|@|@|
So, that's a reasonable confirmation of the doco, and the fact that my Perl version (5.26.0, by the way) is adhering to this.
Anyway, I went back to the code I posted earlier, and added the subroutine requesting inlining back in; however, this time I wrote it like this, so that @keys was constant and couldn't possibly be altered elsewhere due to the lexical scoping of the anonymous block:
{ my @keys = keys %$hash_ref; sub hrkeys () { @keys } }
There was no improvement on the OP's code. I ran it a few times, the "kens/op:" value was now showing 100% (±2%).
With regard to the caching, that's the reason I didn't spend any time trying to check it. The minimal sanity checking (that the OP's and my code were producing equivalent results) showed %$bar had one key ("1275") and its arrayref value held all of the two million elements.
— Ken
In reply to Re^4: Optimize a perl block
by kcott
in thread Optimize a perl block
by IruP
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |