Perl QA 2014 Recap

This year's Perl QA Hackathon has come and gone. I had an amazing time, and

The QA Hackathon is a gathering with the purpose of improving Perl's toolchain, testing infrastructure, and other bits surrounding language development and usage. At it's core is an incredibly friendly and intelligent group of people, and I always leave the conference feeling reinvigorated and motivated to get things done (and with a much larger todo list than I had going in...)

I brought my fiancée and a friend with me (we had a mini-vacation in Lyon after the c…

Perl 5.19.x performance improvements

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


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.


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:

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) {

I ran it 3 times for each test using "time ./" (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.


-- Matthew Horsfall (alh)

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

Devel::Quick - Simple DB::DB routines on the fly

Just wanted to share a new little debugging tool, Devel::Quick.

It allows you to write DB::DB subroutines on the fly, and provides a few variables by default to make things simpler.


DB::DB (the DB subroutine under the DB package) -- if defined when Perl is run under '-d' -- will be executed before every line in the Perl source being run. If the DB::DB call is within a subroutine, you can also peak at the arguments passed into the sub.


A simple example of a module using this is Devel::Trace, which will print out the source code about to be executed for every line.

With Devel::Quick, we can recreate this functionality like so:

$ perl -d:Quick='print ">> $filename:$line $code"'

Or with -e

$ perl -d:Quick='print ">> $filename:$line $code"' -e 'print "Hello!\n";  
my $x = 3 + 5;  
print "X: $x\n";
>> -e:1 print "Hello!\n";
>> -e:2 my $x = 3 + 5; 
>> -e:3 print "X: $x\n";
X: 8

Behind the scenes:

All that Devel::Quick is really doing is wrapping your code in this block:

package DB;

use strict;
use warnings;

sub DB {
    my ($package, $filename, $line,
           $subroutine, $hasargs, $wantarray,
           $evaltext, $is_require, $hints,
           $bitmask, $hinthash) = caller(0);

    my $args = \@_;

    my $code;
        no strict 'refs';
        $code = @{"::_<$filename"}[$line];

    no strict;


By default, strict is turned off to make the one-liners easier, but you can enable it by doing:

perl -d:Quick=-strict,'print "..."'


perl -d:Quick=-s,'print "..."'

For more information, check out Devel::Quick on metacpan.

More Info

For more information on Perl debugging, see:


-- Matthew Horsfall (alh)

Introducing Devel::Nopeep, Devel::GDB::Breakpoint, and Devel::GDB::Parser::Breakpoint

I've created 3 new modules to help me out when working on the Perl core; I'm sharing them in the event others find them useful.

They are:


This module disables the peephole optimiser so that you can see what the op tree would look like before it works its magic (and benchmark the differences, if you like).

For example:

$ perl -MO=Concise -e 'if ($a && $b) {}'
8  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 3 -e:1) v:{ ->3
-     <1> null vK/1 ->8
6        <|> and(other->7) vK/1 ->8
-           <1> null sK/1 ->6
4              <|> and(other->5) sK/1 ->8
->                  <1> ex-rv2sv sK/1 ->4
3                    <$> gvsv(*a) s ->4
-                 <1> ex-rv2sv sK/1 ->-
5                    <$> gvsv(*b) s ->6
-           <@> scope vK ->-
7              <0> stub v ->8
-e syntax OK


$ perl -MDevel::Nopeep -MO=Concise -e 'if ($a && $b) {}'
a  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 3 -e:1) v:{ ->3
-     <1> null vK/1 ->a
8        <|> and(other->9) vK/1 ->-
-           <1> null sK/1 ->8
5              <|> and(other->6) sK/1 ->-
4                 <1> rv2sv sK/1 ->5
3                    <$> gv(*a) s ->4
7                 <1> rv2sv sK/1 ->-
6                    <$> gv(*b) s ->7
-           <@> scope vK ->-
9              <0> stub v ->-
-e syntax OK


This module lets you set breakpoints in your Perl code that you can easily match up to with gdb. If you have a large program and you want to break in different places, you can:

use Devel::GDB::Breakpoint;

breakpoint 3;
breakpoint 4;

And then with gdb:

$ gdb --args perl
(gdb) b bp if val == 3
(gdb) b bp if val == 4
(gdb) run

Each Perl call to breakpoint sets up a call to the C function void bp(int val); that will be called at runtime.


This module builds off of Devel::GDB::Breakpoint and allows you to set breakpoints that will be triggered when perl parses the code in question, way before it ever runs it (think BEGIN {}).

For example:

use Devel::GDB::Parser::Breakpoint;

if ($a && $b && parser_breakpoint 42 && $c) { }

And then like above:

$ gdb --args
(gdb) b bp if val == 42
(gdb) run

I'll be spending a lot more time playing with Perl and might have some more things to share in the near future.


-- Matthew Horsfall (alh)

Announcing Net::RNDC - Communicate with BIND through Perl

I often have need to communicate with ISC's BIND programattically and I haven't found any libraries out there to do that.

Often, what you'll see is a wrapper around BIND's rndc utility that forks, execs, passes it arguments, and then parses the output.

This is okay if you're on a box that can fork and has rndc installed, but that's not a safe assumption.

So I spent some time digging through BIND source and deconstructing the RNDC protocol (which was actually quite fun) and came up with ="…