bennymack has asked for the wisdom of the Perl Monks concerning the following question:
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.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Imperative VS Functional - Imperative wins?
by dragonchild (Archbishop) on Mar 23, 2007 at 19:03 UTC | |
|
Re: Imperative VS Functional - Imperative wins?
by ferreira (Chaplain) on Mar 23, 2007 at 19:07 UTC |