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.


In reply to Imperative VS Functional - Imperative wins? by bennymack

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.