Want to save 10 nanoseconds? Perl v5.20 optimizes a return
at the end of a subroutine to use two fewer ops in the optimized version. During compilation, a subroutine like this one:
sub some_sub { ...; return $foo }
turns into a subroutine like this one, without the return
sub some_sub { ...; $foo }
You can see the difference in the output from the B::Concise module (which you can use through the O
frontend). Prior to v5.20, there are five steps to return the first argument:
$ perl5.18.0 -MO=Concise,baz,-exec -e 'sub baz { return $_[0] }' main::baz: 1 <;> nextstate(main 1 -e:1) v 2 <0> pushmark s 3 <$> aelemfast(*_) s 4 <@> return K 5 <1> leavesub[1 ref] K/REFC,1 -e syntax OK
But, prior to v5.20, if you didn’t use the return
keyword, there are only three steps after the PUSHMARK
isn’t there:
$ perl5.18.0 -MO=Concise,baz,-exec -e 'sub baz { $_[0] }' main::baz: 1 <;> nextstate(main 1 -e:1) v 2 <$> aelemfast(*_) s 3 <1> leavesub[1 ref] K/REFC,1 -e syntax OK
You can read about PUSHMARK
in the perlcall documentation. It’s a signal to perl
to remember where the current stack pointer is.
With v5.20, perl
optimizes the return
version to have the same steps:
$ perl5.20.0 -MO=Concise,baz,-exec -e 'sub baz { return $_[0] }' main::baz: 1 <;> nextstate(main 1 -e:1) v 2 <$> aelemfast(*_) s 3 <1> leavesub[1 ref] K/REFC,1 -e syntax OK $ perl5.20.0 -MO=Concise,baz,-exec -e 'sub baz { $_[0] }' main::baz: 1 <;> nextstate(main 1 -e:1) v 2 <$> aelemfast(*_) s 3 <1> leavesub[1 ref] K/REFC,1 -e syntax OK
This will be happy news to people who stick to Perl Best Practices, which recommends that you always use an explicit return
. Damian’s recommendation is to denote intent, but now you don’t suffer if it’s the last statement in the subroutine.