Erik Bennett
Erik Bennett

Reputation: 1099

Perl optimizer question: Will the perl compiler optimize away all of these temporary variables?

I've got a pretty simple piece of arithmetic, but for readability and correctness, I've expanded it out into a bunch of temporary variables. It's easier to read, change, and examine partial pieces of the expression.

My question is, will this code take a run-time beating just because it's expanded? I don't know how the perl compiler works, but in 'C', or such, these extra (not quite) variables would be optimized right out of existence.

my $targetBasis = $$s{"basis"} * $nextBasisPct;
my $dollarsHeld = $$s{"basis"} * $$s{"held"};
my $targetDollars = $dollarsHeld + $opt{"buyDollars"};
my $targetShares = $targetDollars / $targetBasis;
my $newShares = $targetShares - $$s{"held"};
my $targetPrice = $opt{"buyDollars"} / $newShares;

Thanks.

-E

I just got done expanding this from a nasty looking one liner, only to find that it was correct. I'd rather not put it back to unreadable if there's no reason to do so.

Upvotes: 5

Views: 211

Answers (3)

ikegami
ikegami

Reputation: 385897

No.

The following The compiled version of the program

$ perl -MO=Concise,-exec a.pl
1  <0> enter
2  <;> nextstate(main 2 a.pl:2) v:*,&,{,x*,x&,x$,$
3  <0> padrange[$s:2,8; %opt:2,8; $targetBasis:2,8] vM/LVINTRO,range=3
4  <;> nextstate(main 3 a.pl:3) v:*,&,{,x*,x&,x$,$
5  <+> multideref($s->{"basis"}) sK/STRICT
6  <+> multideref($s->{"held"}) sK/STRICT
7  <2> multiply[t5] sK/2
8  <0> padsv[$dollarsHeld:3,8] sRM*/LVINTRO
9  <2> sassign vKS/2
a  <;> nextstate(main 4 a.pl:4) v:*,&,{,x*,x&,x$,$
b  <0> padsv[$dollarsHeld:3,8] s
c  <+> multideref($opt{"buyDollars"}) sK
d  <2> add[t7] sK/2
e  <0> padsv[$targetDollars:4,8] sRM*/LVINTRO
f  <2> sassign vKS/2
g  <;> nextstate(main 5 a.pl:5) v:*,&,{,x*,x&,x$,$
h  <0> padsv[$targetDollars:4,8] s
i  <0> padsv[$targetBasis:2,8] s
j  <2> divide[t9] sK/2
k  <0> padsv[$targetShares:5,8] sRM*/LVINTRO
l  <2> sassign vKS/2
m  <;> nextstate(main 6 a.pl:6) v:*,&,{,x*,x&,x$,$
n  <0> padsv[$targetShares:5,8] s
o  <+> multideref($s->{"held"}) sK/STRICT
p  <2> subtract[t11] sK/2
q  <0> padsv[$newShares:6,8] sRM*/LVINTRO
r  <2> sassign vKS/2
s  <;> nextstate(main 7 a.pl:7) v:*,&,{,x*,x&,x$,$
t  <+> multideref($opt{"buyDollars"}) sK
u  <0> padsv[$newShares:6,8] s
v  <2> divide[t13] sK/2
w  <0> padsv[$targetPrice:7,8] sRM*/LVINTRO
x  <2> sassign vKS/2
y  <@> leave[1 ref] vKP/REFC
a.pl syntax OK

Note that I prepended the following to the program first:

use strict;
my ($s, %opt, $targetBasis);

Optimizing the variables away would save copying a value into them, but copying a numerical scalar into another one is very cheap.

I would leave the code in its readable form. Readability is far more important than saving a few nanoseconds.

Upvotes: 9

Dave Cross
Dave Cross

Reputation: 69274

You already have a couple of good answers to your question, but I wanted to add a couple of tips for improving the readability of your code.

  • Hash keys don't need to be quoted unless they contain whitespace. So $opt{"buyDollars"}, for example, can be written as $opt{buyDollars}.
  • It looks like you have a hash reference in $s. The standard way to access a value from a hash reference is $s->{key}. You're using $$s{key} which works, but which will be very confusing to most people reading your code.

Upvotes: 5

Grinnz
Grinnz

Reputation: 9231

In general, Perl does not ever optimize out variables, only constant expressions, because these are known during the parsing and compilation phase, whereas variable assignment happens at runtime. Consider that any of those variables could be used again later in the scope, or a reference to them could be taken by something and used elsewhere. The Perl parser works sequentially so that would be really difficult to account for.

As for your concerns, unless you are writing code with a real-time requirement (why would you use Perl for this?) or running this code in a loop millions of times, the overhead of variable declaration is not something to be concerned about. Sub calls are slightly more noticeable, method calls moreso, but inefficient algorithms dwarf those concerns. When in doubt, benchmark.

Upvotes: 5

Related Questions