Dear Perl Mavens,
I was messing around with a simple chunk of imperative code and I was curious if flipping it around into a functional one-liner would make it faster. But apparently not... Although my method of doing so was most likely NOT optimal as is normally the case.
I have a feeling the answer is in the layout of the bytecode so I've posted it here for the convenience of the monks who cannot compile to byte code in there head 8^)=
Imperative
$ perl -MO=Concise -e '
my @tokens = split /\:\:/, $ARGV[0];
return ( q[], $tokens[0] ) if scalar( @tokens ) == 1;
return ( $tokens[0], $tokens[1] ) if scalar( @tokens ) == 2;
my $function = pop @tokens;
return ( join( q[::], @tokens), $function );
'
1c <@> leave[1 ref] vKP/REFC ->(end)
1 <0> enter ->2
2 <;> nextstate(main 1 -e:2) v ->3
a <2> aassign[t3] vKS ->b
- <1> ex-list lK ->8
3 <0> pushmark s ->4
7 <@> split[t2] lK ->8
4 </> pushre(/"::"/) s/64 ->5
- <1> ex-aelem sK/2 ->6
- <1> ex-rv2av sKR/1 ->-
5 <$> aelemfast(*ARGV) s ->6
- <0> ex-const s ->-
6 <$> const(IV 0) s ->7
- <1> ex-list lK ->a
8 <0> pushmark s ->9
9 <0> padav[@tokens:1,3] lRM*/LVINTRO ->a
b <;> nextstate(main 2 -e:3) v ->c
- <1> null vK/1 ->m
f <|> and(other->g) vK/1 ->m
e <2> eq sK/2 ->f
- <1> scalar sK/1 ->d
c <0> padav[@tokens:1,3] s ->d
d <$> const(IV 1) s ->e
l <@> return KP ->m
g <0> pushmark s ->h
h <$> const(PV "") s ->i
k <2> aelem sK/2 ->l
i <0> padav[@tokens:1,3] sR ->j
j <$> const(IV 0) s ->k
m <;> nextstate(main 2 -e:4) v ->n
- <1> null vK/1 ->z
q <|> and(other->r) vK/1 ->z
p <2> eq sK/2 ->q
- <1> scalar sK/1 ->o
n <0> padav[@tokens:1,3] s ->o
o <$> const(IV 2) s ->p
y <@> return KP ->z
r <0> pushmark s ->s
u <2> aelem sK/2 ->v
s <0> padav[@tokens:1,3] sR ->t
t <$> const(IV 0) s ->u
x <2> aelem sK/2 ->y
v <0> padav[@tokens:1,3] sR ->w
w <$> const(IV 1) s ->x
z <;> nextstate(main 2 -e:5) v ->10
13 <2> sassign vKS/2 ->14
11 <1> pop sK/1 ->12
10 <0> padav[@tokens:1,3] lRM ->11
12 <0> padsv[$function:2,3] sRM*/LVINTRO ->13
14 <;> nextstate(main 3 -e:6) v ->15
1b <@> return KP ->1c
15 <0> pushmark s ->16
19 <@> join[t5] sK/2 ->1a
16 <0> pushmark s ->17
17 <$> const(PV "::") s ->18
18 <0> padav[@tokens:1,3] l ->19
1a <0> padsv[$function:2,3] ->1b
-e syntax OK
Functional
$ perl -MO=Concise -e 'return map({join(q[::], @$_[0 .. $#$_ - 1]), $$_[$#$_];} [split(/::/, $ARGV[0], 0)]);'
17 <@> leave[1 ref] vKP/REFC ->(end)
1 <0> enter ->2
2 <;> nextstate(main 2 -e:1) v ->3
16 <@> return K ->17
3 <0> pushmark s ->4
d <|> mapwhile(other->e)[t9] K/1 ->16
c <@> mapstart K*/2 ->d
4 <0> pushmark s ->5
- <1> null lK/1 ->5
- <1> null lK/1 ->d
- <@> scope lK ->d
- <0> ex-nextstate v ->e
13 <@> list lK ->-
e <0> pushmark s ->f
u <@> join[t6] sK/2 ->v
f <0> pushmark s ->g
g <$> const(PV "::") s ->h
t <@> aslice lK ->u
h <0> pushmark s ->i
- <1> null lK/1 ->q
p <1> flop lK ->q
15 <1> flip[t5] lK/LINENUM ->q
i <|> range(other->j)[t4] lK/1
+ ->14
14 <$> const(IV 0) s ->15
o <2> subtract[t3] sK/2 ->p
m <1> av2arylen sK/1 ->n
l <1> rv2av[t2] sKR/1
+ ->m
k <1> rv2sv sKM/DR
+EFAV,1 ->l
j <$> gv(*_) s
+->k
n <$> const(IV 1) s ->o
s <1> rv2av[t1] sKR/1 ->t
r <1> rv2sv sKM/DREFAV,1 ->s
q <$> gv(*_) s ->r
12 <2> aelem sK/2 ->13
x <1> rv2av sKR/1 ->y
w <1> rv2sv sKM/DREFAV,1 ->x
v <$> gv(*_) s ->w
11 <1> av2arylen sK/1 ->12
10 <1> rv2av[t7] sKR/1 ->11
z <1> rv2sv sKM/DREFAV,1 ->10
y <$> gv(*_) s ->z
b <1> srefgen sKM/1 ->c
- <1> ex-list lKRM ->b
a <@> anonlist sKRM/1 ->b
5 <0> pushmark s ->6
9 <@> split[t8] lK ->a
6 </> pushre(/"::"/) s/64 ->7
- <1> ex-aelem sK/2 ->8
- <1> ex-rv2av sKR/1 ->-
7 <$> aelemfast(*ARGV) s ->8
- <0> ex-const s ->-
8 <$> const(IV 0) s ->9
-e syntax OK
And the output of the benchmark looks something like this:
Rate functional_3 functional_2 imperative_3 functiona
+l_1 imperative_2 imperative_1
functional_3 245059/s -- -12% -16% -
+24% -36% -54%
functional_2 278368/s 14% -- -5% -
+13% -28% -48%
imperative_3 292322/s 19% 5% --
+-9% -24% -45%
functional_1 321554/s 31% 16% 10%
+ -- -17% -39%
imperative_2 385506/s 57% 38% 32%
+20% -- -27%
imperative_1 531129/s 117% 91% 82%
+65% 38% --
Thanks for any insights you can lend. Sorry if any of my terms are misleading/incorrect.