Does Perl micro-optimize?

Discussion in 'Perl Misc' started by rihad, Oct 10, 2007.

  1. rihad

    rihad Guest

    Hello there,

    Say we have a $hash:

    if ($hash{'A-String-Of-Any-Length'} eq 'foo') { ... }
    else if ($hash{'A-String-Of-Any-Length'} eq 'bar') { ... }

    Would Perl notice that hash lookup needs to be resolved only once, and
    optimize further accesses? Or does one need to explicitly use a $tmp
    for that?

    Thanks.
    rihad, Oct 10, 2007
    #1
    1. Advertising

  2. rihad

    Mirco Wahab Guest

    rihad wrote:
    > Hello there,
    >
    > Say we have a $hash:
    >
    > if ($hash{'A-String-Of-Any-Length'} eq 'foo') { ... }
    > else if ($hash{'A-String-Of-Any-Length'} eq 'bar') { ... }
    >
    > Would Perl notice that hash lookup needs to be resolved only once, and
    > optimize further accesses? Or does one need to explicitly use a $tmp
    > for that?


    Perl5 does not, you can check that out for yourself
    by the following snippet:

    my %hash = ('A_String_Of_Any_Length', 'FUD', map +(rand,rand),1..1000 );

    1: if( $hash{A_String_Of_Any_Length} eq 'foo') {
    print "do a lot of thinngs\n"
    }
    2: elsif( $hash{A_String_Of_Any_Length} eq 'bar') {
    print "do not so simple things\n"
    }
    else {
    print "do nothing\n"
    }


    if viewed by perl -MO=Bblock rihad.pl,
    it shows both hash lookups:
    ...
    OP (0x1838050) padhv [1]
    1: SVOP (0x1838030) const [14] PV (0x1969814) "A_String_Of_Any_Length"
    BINOP (0x183800c) helem
    SVOP (0x1837fec) const [15] PV (0x196982c) "foo"
    BINOP (0x1837fc8) seq

    LOGOP (0x1837b40) cond_expr
    OP (0x1837f08) pushmark
    SVOP (0x1837f48) const [16] PV (0x1969820) "do a lot of thinngs\n"
    LISTOP (0x1837f24) print

    OP (0x1837e8c) padhv [1]
    2: SVOP (0x1837e6c) const [17] PV (0x1969838) "A_String_Of_Any_Length"
    BINOP (0x1837e48) helem
    SVOP (0x1837e28) const [18] PV (0x1969850) "bar"
    BINOP (0x1837e04) seq

    LOGOP (0x1837b84) cond_expr
    ...

    Regards

    M.
    Mirco Wahab, Oct 10, 2007
    #2
    1. Advertising

  3. rihad

    Ben Morrow Guest

    Quoth rihad <>:
    > Hello there,
    >
    > Say we have a $hash:
    >
    > if ($hash{'A-String-Of-Any-Length'} eq 'foo') { ... }
    > else if ($hash{'A-String-Of-Any-Length'} eq 'bar') { ... }
    >
    > Would Perl notice that hash lookup needs to be resolved only once, and
    > optimize further accesses?


    Nope.

    > Or does one need to explicitly use a $tmp for that?


    Yup. Note that under some circumstances

    my $tmp = $hash{foo};

    can be slower than redoing the lookup, notably if $hash{foo} contains a
    long string that must be copied. This can be got around with refs, but
    that's messy. As ever, profile before you start thinking about
    optimizing.

    Note also that perl couldn't possibly perform this optimization, as it
    would break tied hashes, or, at any rate, make the semantics highly
    unreliable.

    Ben
    Ben Morrow, Oct 10, 2007
    #3
  4. rihad

    Guest

    rihad <> wrote:
    > Hello there,
    >
    > Say we have a $hash:
    >
    > if ($hash{'A-String-Of-Any-Length'} eq 'foo') { ... }
    > else if ($hash{'A-String-Of-Any-Length'} eq 'bar') { ... }


    Perl doesn't have an "else if". It has "elsif"

    > Would Perl notice that hash lookup needs to be resolved only once, and
    > optimize further accesses?


    I don't think so, but if it did do this kind of thing ever, it would
    probably vary a lot from situation to situation and version to version.
    And imagine the chaos this could cause for tied hashes.

    If the look-up string were in a variable, I know that in some situations
    and with some versions, the hashed integer of the (potentially very large)
    string can be stored in the SV rather than needing to be recomputed. I
    don't know what happens with literals.

    > Or does one need to explicitly use a $tmp
    > for that?


    If one wants the lookup not to be done twice, then you would need to use
    a temp variable. It seems that this is at least as likely to make things
    slower as faster, though.

    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    The costs of publication of this article were defrayed in part by the
    payment of page charges. This article must therefore be hereby marked
    advertisement in accordance with 18 U.S.C. Section 1734 solely to indicate
    this fact.
    , Oct 10, 2007
    #4
  5. On Wed, 10 Oct 2007 10:23:01 -0700, rihad <> wrote:

    >if ($hash{'A-String-Of-Any-Length'} eq 'foo') { ... }
    >else if ($hash{'A-String-Of-Any-Length'} eq 'bar') { ... }


    If you have many such chained elsif's, then you *may* want to go the
    road of HoH. I seldom if ever use explicit elsif's.

    >Would Perl notice that hash lookup needs to be resolved only once, and
    >optimize further accesses? Or does one need to explicitly use a $tmp
    >for that?


    Sometimes I like to exploit C<for>'s aliasing properties for this
    kinda things. Such use is occasionally controversial.


    Michele
    --
    {$_=pack'B8'x25,unpack'A8'x32,$a^=sub{pop^pop}->(map substr
    (($a||=join'',map--$|x$_,(unpack'w',unpack'u','G^<R<Y]*YB='
    ..'KYU;*EVH[.FHF2W+#"\Z*5TI/ER<Z`S(G.DZZ9OX0Z')=~/./g)x2,$_,
    256),7,249);s/[^\w,]/ /g;$ \=/^J/?$/:"\r";print,redo}#JAPH,
    Michele Dondi, Oct 10, 2007
    #5
  6. rihad

    rihad Guest

    On Oct 10, 10:41 pm, Ben Morrow <> wrote:
    > Quoth rihad <>:
    > my $tmp = $hash{foo};
    >
    > can be slower than redoing the lookup, notably if $hash{foo} contains a
    > long string that must be copied.


    Why would Perl want to copy the value? Doesn't it do copy-on-write or
    similar?
    rihad, Oct 11, 2007
    #6
  7. rihad <> wrote:
    > On Oct 10, 10:41 pm, Ben Morrow <> wrote:
    >> Quoth rihad <>:
    >> my $tmp = $hash{foo};
    >>
    >> can be slower than redoing the lookup, notably if $hash{foo} contains a
    >> long string that must be copied.

    >
    > Why would Perl want to copy the value?



    Because you told it to, via an assignment operator.


    > Doesn't it do copy-on-write or
    > similar?



    The code above is doing a write (to the $tmp variable).


    --
    Tad McClellan
    email: perl -le "print scalar reverse qq/moc.noitatibaher\100cmdat/"
    Tad McClellan, Oct 11, 2007
    #7
  8. rihad

    Ben Morrow Guest

    Quoth Tad McClellan <>:
    > rihad <> wrote:
    > > On Oct 10, 10:41 pm, Ben Morrow <> wrote:
    > >> Quoth rihad <>:
    > >> my $tmp = $hash{foo};
    > >>
    > >> can be slower than redoing the lookup, notably if $hash{foo} contains a
    > >> long string that must be copied.

    > >
    > > Why would Perl want to copy the value?

    >
    > Because you told it to, via an assignment operator.
    >
    > > Doesn't it do copy-on-write or
    > > similar?

    >
    > The code above is doing a write (to the $tmp variable).


    There is no good reason why perl couldn't copy-on-write the scalar: that
    is, make a new SV that points at the same string buffer until one of
    them is modified. There is some support for this in 5.9.x, but I don't
    think it's ready to be used yet (?).

    Ben
    Ben Morrow, Oct 11, 2007
    #8
  9. rihad

    rihad Guest

    On Oct 11, 5:43 pm, Ben Morrow <> wrote:
    > There is some support for this in 5.9.x, but I don't
    > think it's ready to be used yet (?).
    >


    Noo, you've got to be kidding... At least subroutine arguments are
    always passed by reference in Perl (which is good for speed, but bad
    if you unintentionally modify them).

    On a side note, and I won't be the first one to say this: Perl is
    difficult. Too many special cases. Or maybe I have this impression
    because Programming Perl by Larry Wall is very hard reading.
    rihad, Oct 11, 2007
    #9
  10. rihad

    Mirco Wahab Guest

    rihad wrote:
    > On Oct 11, 5:43 pm, Ben Morrow <> wrote:
    >> There is some support for this in 5.9.x, but I don't
    >> think it's ready to be used yet (?).

    >
    > Noo, you've got to be kidding... At least subroutine arguments are
    > always passed by reference in Perl (which is good for speed, but bad
    > if you unintentionally modify them).


    In perl, only SV's (pointers to scalar values) or RV's (pointers
    to those SV's, to Arrays, Hashes or whatever) are passed into
    subroutines. There are "idiomatic expressions" for taking the
    value they point to out into (copies) variables,
    like: my ($var1, $var2) = @_

    > On a side note, and I won't be the first one to say this: Perl is
    > difficult. Too many special cases. Or maybe I have this impression
    > because Programming Perl by Larry Wall is very hard reading.


    Thats true in my opinion, The "LLama Book"
    (http://www.oreilly.com/catalog/lperl3/) is
    much better for you if you jump into Perl
    from somewhere else. The "Camel Book",
    (http://www.oreilly.com/catalog/pperl3/index.html)
    which is the book you mentioned, will be most
    valuable if you are at least somehow "intermediate".

    Regards

    M.
    Mirco Wahab, Oct 11, 2007
    #10
  11. On Thu, 11 Oct 2007 06:46:27 -0700, rihad <> wrote:

    >> There is some support for this in 5.9.x, but I don't
    >> think it's ready to be used yet (?).
    >>

    >
    >Noo, you've got to be kidding... At least subroutine arguments are
    >always passed by reference in Perl (which is good for speed, but bad
    >if you unintentionally modify them).


    Nooo, arguments passing is known to be terribly inefficient in Perl.
    Ask Ilya!!

    >On a side note, and I won't be the first one to say this: Perl is
    >difficult. Too many special cases. Or maybe I have this impression


    Yes it is, and yes there are. But you're not required to know them all
    from scratch.

    However, if you're patient enough, Perl 6 will be an even more complex
    language whose complexity will be built by the complex interaction
    between simpler pieces, in a consistent and orthogonal manner, with no
    special cases.


    Michele
    --
    {$_=pack'B8'x25,unpack'A8'x32,$a^=sub{pop^pop}->(map substr
    (($a||=join'',map--$|x$_,(unpack'w',unpack'u','G^<R<Y]*YB='
    ..'KYU;*EVH[.FHF2W+#"\Z*5TI/ER<Z`S(G.DZZ9OX0Z')=~/./g)x2,$_,
    256),7,249);s/[^\w,]/ /g;$ \=/^J/?$/:"\r";print,redo}#JAPH,
    Michele Dondi, Oct 11, 2007
    #11
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jason Smith

    Does Python optimize regexes?

    Jason Smith, Jun 29, 2004, in forum: Python
    Replies:
    5
    Views:
    316
  2. Blackbird

    How much does Python optimize?

    Blackbird, Mar 3, 2006, in forum: Python
    Replies:
    4
    Views:
    453
    Alex Martelli
    Mar 4, 2006
  3. George2
    Replies:
    4
    Views:
    394
    Ron Natalie
    Dec 28, 2007
  4. Tristan Wibberley
    Replies:
    1
    Views:
    348
    Erik Wikström
    Dec 27, 2007
  5. KOFKS
    Replies:
    5
    Views:
    1,193
Loading...

Share This Page