Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 463
Erik Bennett Avatar asked Feb 08 '19 20:02

Erik Bennett


2 Answers

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.

like image 176
ikegami Avatar answered Sep 28 '22 14:09

ikegami


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.

like image 36
Grinnz Avatar answered Sep 28 '22 15:09

Grinnz