It is astonishing how different can be a performance of two trivial functions accomplishing the same task. In the last month, I needed a function to convert a string representing a binary number (i.e. "0101") to an integer (5). The first time, for a script that helps verify some VHDL test-benches, I used the following implementation from the Cookbook:
sub bin2dec { return unpack("N", pack("B32", substr("0" x 32 . shift, -32))); }
The second time I forgot about the first time (typical), and implemented such a function myself:
sub binstr2num { my @arr = split(//, $_[0]); my $val = 0; my $deg = 1; for (my $i = 31; $i >= 0; --$i) { $val += $deg if ($arr[$i] == 1); $deg *= 2; } return $val; }
The second time it was for a toy implementation of a genetic algorithm (that "guesses" a number), so I noticed some performance problems - it ran too slow !
So, a little optimization was required. No problems, Perl gives all the tools for that. I ran perl on my script with -d:DProf, then run dprofpp, to see that my function binstr2num was taking most of the time (it is called quite often).
Only now I recalled that I used an implementation from the Cookbook only recently. And if it's from the Cookbook, it must be Good (TM), right ?
Right !! The Benchmark module came in very handy here, and the following was quickly coded:
my $vec = "01111110110101101100001011010101"; timethese($count, { 'bin2dec' => sub {bin2dec($vec)}, 'binstr2num' => sub {binstr2num($vec)}});
And viola !
Benchmark: timing 1000000 iterations of bin2dec, binstr2num... bin2dec: 2 wallclock secs ( 2.59 usr + 0.00 sys = 2.59 CPU) @ 385505.01/s (n=1000000) binstr2num: 100 wallclock secs (98.47 usr + 0.00 sys = 98.47 CPU) @ 10155.58/s (n=1000000)
This is one big difference, ouch !!