Perl FAQ 4.14: What's the fastest way to code up a given task in perl?

Perl FAQ 4.14

What's the fastest way to code up a given task in perl?

Post it to comp.lang.perl.misc and ask Tom or Randal a question about it. ;)

Because Perl so lends itself to a variety of different approaches for any given task, a common question is which is the fastest way to code a given task. Since some approaches can be dramatically more efficient that others, it's sometimes worth knowing which is best. Unfortunately, the implementation that first comes to mind, perhaps as a direct translation from C or the shell, often yields suboptimal performance. Not all approaches have the same results across different hardware and software platforms. Furthermore, legibility must sometimes be sacrificed for speed.

While an experienced perl programmer can sometimes eye-ball the code and make an educated guess regarding which way would be fastest, surprises can still occur. So, in the spirit of perl programming being an empirical science, the best way to find out which of several different methods runs the fastest is simply to code them all up and time them. For example:

$COUNT = 10_000; $| = 1;

print "method 1: ";

($u, $s) = times;
for ($i = 0; $i < $COUNT; $i++) {
    # code for method 1
}
($nu, $ns) = times;
printf "%8.4fu %8.4fs\n", ($nu - $u), ($ns - $s);

print "method 2: ";

($u, $s) = times;
for ($i = 0; $i < $COUNT; $i++) {
    # code for method 2
}
($nu, $ns) = times;
printf "%8.4fu %8.4fs\n", ($nu - $u), ($ns - $s);

Perl5 includes a new module called Benchmark.pm. You can now simplify the code to use the Benchmarking, like so:

use Benchmark;

timethese($count, {
    Name1 => '...code for method 1...',
    Name2 => '...code for method 2...',
    ... });

It will output something that looks similar to this:

Benchmark: timing 100 iterations of Name1, Name2...
    Name1:  2 secs (0.50 usr 0.00 sys = 0.50 cpu)
    Name2:  1 secs (0.48 usr 0.00 sys = 0.48 cpu)

For example, the following code will show the time difference between three different ways of assigning the first character of a string to a variable:

use Benchmark;
timethese(100000, {
    'regex1' => '$str="ABCD"; $str =~ s/^(.)//; $ch = $1',
    'regex2' => '$str="ABCD"; $str =~ s/^.//; $ch = $&',
    'substr' => '$str="ABCD"; $ch=substr($str,0,1); substr($str,0,1)="",
});

The results will be returned like this:

Benchmark: timing 100000 iterations of regex1, regex2, substr...
   regex1: 11 secs (10.80 usr   0.00 sys =  10.80 cpu)
   regex2: 10 secs (10.23 usr   0.00 sys =  10.23 cpu)
   substr:  7 secs ( 5.62 usr   0.00 sys =   5.62 cpu)

For more specific tips, see the section on Efficiency in the ``Other Oddments'' chapter at the end of the Camel Book.


Other resources at this site: