Perl 5.19.9 was released today, and it includes some exciting new features like subroutine signatures, and postfix dereferencing.

The 5.19.X line also includes a number of optimisations that I'd like to discuss briefly, without going into too much detail (I hope).

Combined and/or operators in void context

The first improvement was added back in 5.19.6, and effects and and or operators in void context. It improves the short-cirtcuiting logic of and/or operations when inside of an if statement.

What this means is that in many cases, this:

if ($var1 || $var2) { ... }

will be ever-so-slightly faster if $var1 is true than it used to, and

unless ($var1 && $var2) { ... }

will be ever-so-slightly faster if $var1 is false. This is about a 2% speed improvement in my tests, for each of the above constructs being evaluated.

return at end of sub optimised out

This improvement was added in 5.19.8, and optimises out a return statement at the end of a sub so that:

return $x;

is compiled as

$x;

which is a fair bit faster (about 10%) since a return statement actually includes a few more ops behind the scenes than necessary for these cases.

Multiple single PADOPs combined into a list

The final optimisation was just released with 5.19.9 and turns multiple single PADOPs into its list form.

That means this:

my $x; my $y;

becomes this:

my ($x, $y);

Which then can be optimised into a single PADRANGE op which was added back in 5.18.0.

This gives a speedup of about 7% in the above case, and will have a greater effect if more PADOPS (my $x; my @y; my %z) are used in a row.

Testing

For light testing, I used a best-case scenario subroutine for all above optimisations, and enabled each in turn to see how the sub improved. (I didn't test them individually, so numbers may vary. IE: I enabled return optimisations, then padrange optimisations, then and/or in void context optimisations).

Using this program:

#!/usr/bin/perl use strict; use warnings; my $aa = 1; my $bb = 0; sub somesub { my $x; my $y; if ($aa || $bb) { $x = 1; } return $x; } for (1..50_000_000) { somesub(); }

I ran it 3 times for each test using "time ./opt.pl" (I know, start up costs skew results, but only ever so slightly in comparison to what was being tested in this case, and yes, 3 is not enough to give a really good average...), and averaged out the results:

Original: 6.69s Optimise out return: 6.03s 10% speedup Optimise my $x; my $y; into my ($x; $y);: 5.62s 7% speedup Optimise if ($a || $b) { ... } if $a is true: 5.53s 2% speedup Total: 19% speedup

I'm pretty happy with the results.

Playing with Perl's optimiser was a lot of fun (and a fair amount of frustration :)), and I hope to do more work in this area.

Perl 5.20 (which is set to release May of this year) will includes these optimisations, and I hope to have many more for 5.22 next year.

Cheers,

-- Matthew Horsfall (alh)

P.S. If anyone wants more in-depth details of the optimisations, I'm happy to provide them. (Separate blog posts?)