Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Re^11: Why does each() always re-evaluate its argument? ("for_list" )

by NERDVANA (Deacon)
on Dec 09, 2023 at 10:17 UTC ( [id://11156206]=note: print w/replies, xml ) Need Help??


in reply to Re^10: Why does each() always re-evaluate its argument? ("for_list" )
in thread Why does each() always re-evaluate its argument?

It's fine to reset the iterator even if they don't use it, so that's not proof. But, in fact you're right; in Perl_hv_pushkv there is

EXTEND_MORTAL(nkeys); EXTEND(SP, ext); while ((entry = hv_iternext(hv))) { if (flags & 1) { SV *keysv = newSVhek(HeKEY_hek(entry)); SvTEMP_on(keysv); PL_tmps_stack[++PL_tmps_ix] = keysv; PUSHs(keysv); } if (flags & 2) PUSHs(HeVAL(entry)); }

I'm rather surprised they didn't optimize that to just iterate the hashtable directly. I'm sure there are some special cases handled by hv_iternext, but they could have just tested for that first.

Extending the stack by one element or by 200,000 has the same fixed performance cost.

How do you figure? It has to allocate the current size + 1.6MB of ram and initialize all of it. (and as the code above shows, it also has to grow the temps stack by 800KB and initialize that) Overwriting a pair of scalars in a loop would extend by 2 and probably fall within the size of the existing stack(s) anyway.

  • Comment on Re^11: Why does each() always re-evaluate its argument? ("for_list" )
  • Download Code

Replies are listed 'Best First'.
Re^12: Why does each() always re-evaluate its argument? ("for_list" )
by ikegami (Patriarch) on Dec 11, 2023 at 03:02 UTC

    I'm rather surprised they didn't optimize that to just iterate the hashtable directly.

    You mean inline hv_iternext? The compiler will do that if appropriate. But that's unlikely since hv_iternext is quite big. It would make no sense to put a copy of that code in the function you showed.

    How do you figure? It has to allocate the current size + 1.6MB of ram and initialize all of it.

    No initialization is needed.

      I mean like this recipe that I've seen in various places:
      STRLEN max = HvMAX(hv); STRLEN i; for (i = 0; i <= max; i++) { HE *entry = (HvARRAY(hv))[i]; for (; entry; entry = HeNEXT(entry)) {
      Of course this can only be used if it isn't magical or tied and so on, but it would be way faster than calling hv_iternext, inlined or not.

        Of course this can only be used if it isn't magical or tied and so on

        Does it really matter if it's faster if it doesn't work?

Re^12: Why does each() always re-evaluate its argument? ("for_list" )
by LanX (Saint) on Dec 09, 2023 at 14:53 UTC
    Even if caching the whole list is faster than iterating step by step, it'll be slower if a big loop is left early.

    The question is how long that list has to be.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    see Wikisyntax for the Monastery

    ) like with last

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11156206]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others exploiting the Monastery: (6)
As of 2024-04-18 21:04 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found