http://www.perlmonks.org?node_id=106122

bladx has asked for the wisdom of the Perl Monks concerning the following question:

Hey I have a question about the efficiency of when I am going to print out a variable, after referencing it for instance (since I have recently read the man page perlreftut.)

Is there any speed difference between putting it like this:

${$variablefoo};

and this:

$$variablefoo;

? Thanks for any clarification. My guess would be that it is simply cleaner to write it out one way rather than another, but sometimes does it have to do with speed too?

Andy Summers

Replies are listed 'Best First'.
Re: Efficiency of $$var, ${$var}
by athomason (Curate) on Aug 20, 2001 at 09:09 UTC
    The difference is negligible. Benchmark will frequently answer questions like these from a practical standpoint:
    use Benchmark 'cmpthese'; use strict; my $x = 0; our $y = \$x; cmpthese( 10000000, { 'braces' => sub { return ${ $y } }, 'nobraces' => sub { return $$y }, });
    My output is this:
    Benchmark: timing 10000000 iterations of braces, nobraces... braces: 2 wallclock secs ( 1.87 usr + 0.00 sys = 1.87 CPU) @ 53 +47593.58/s (n=10000000) nobraces: 1 wallclock secs ( 1.87 usr + 0.00 sys = 1.87 CPU) @ 53 +47593.58/s (n=10000000) Rate nobraces braces nobraces 5347594/s -- 0% braces 5347594/s 0% --
    If there is a difference, it's not terribly significant. For more complicated references, there may be some loss one way or another, but I doubt it would be much, if anything. Best as I could tell from using B::Deparse, the opcodes generated are different, but they likely work out to about the same thing (at least for hard refereneces... which you should be using exclusively). I find braces generally obnoxious, and so I avoid them when possible. However, they're a necessary evil, as demonstrated by the difference in y and z in the following:
    my $x = [ [ 1, 2 ], [ 3, 4 ] ]; my @y = @$x->[ 0 ]; my @z = @{ $x->[ 0 ] };
Re: Efficiency of $$var, ${$var}
by MZSanford (Curate) on Aug 20, 2001 at 13:35 UTC
        They call me obsessed. They call me crazy. But fear not, the Over-Optimizer is here. I, like many programmers, will optimise the smallest code just to eek out the smallest gains. In doing this you learn the art of optimsation.Also, i am a programmer, not an english teacher, so please ignore any spelling errors. See below :

    Checking : $$var vs. ${$var}

    Test Code :
    #!/usr/bin/perl $a = "foo"; $b = \$a; print "b : $$b\n"; print "b2 : ${$b}\n";

    Tests : perl -MO=Deparse,-p test_ref.pl
        if inconclusive ...
    perl -Dt  test_ref.pl

    Test 1 :
    perl -MO=Deparse,-p test_ref.pl ($a = 'foo'); ($b = (\$a)); print("b : $$b\n"); print("b2 : ${$b;}\n"); test_ref.pl syntax OK

    hmmmm, no real help there. Actually, based on the ";" added on the second print, ${$var} might be slower (which would make my guess wrong).

    Test 2 :
    perl -Dt test_ref.pl (test_ref.pl:0) enter (test_ref.pl:0) nextstate (test_ref.pl:3) const(PV("foo"\0)) (test_ref.pl:3) gvsv(main::a) (test_ref.pl:3) sassign (test_ref.pl:3) nextstate (test_ref.pl:4) gvsv(main::a) (test_ref.pl:4) srefgen (test_ref.pl:4) gvsv(main::b) (test_ref.pl:4) sassign (test_ref.pl:4) nextstate (test_ref.pl:7) pushmark (test_ref.pl:7) const(PV("b : "\0)) (test_ref.pl:7) gvsv(main::b) (test_ref.pl:7) rv2sv (test_ref.pl:7) concat (test_ref.pl:7) const(PV("\n"\0)) (test_ref.pl:7) concat (test_ref.pl:7) print b : foo (test_ref.pl:7) nextstate (test_ref.pl:9) pushmark (test_ref.pl:9) const(PV("b2 : "\0)) (test_ref.pl:9) gvsv(main::b) (test_ref.pl:9) rv2sv (test_ref.pl:9) concat (test_ref.pl:9) const(PV("\n"\0)) (test_ref.pl:9) concat (test_ref.pl:9) print b2 : foo (test_ref.pl:9) leave

    Eurica !

    Now, for those who did not spot it, here is what i am seeing :
        The first line which has (test_ref.pl:7) is entering the print statement. Reading from there to the end, there are two duplicated sections, meaning the exact same path is used for both de-referencers. So, to show it more clearly (sorry about any code wrapping) :
    (test_ref.pl:4) nextstate (test_ref.pl:7) nextstate (test_ref.pl:7) pushmark (test_ref.pl:9) pushmark (test_ref.pl:7) const(PV("b : "\0)) (test_ref.pl:9) const(PV("b2 : " +\0)) (test_ref.pl:7) gvsv(main::b) (test_ref.pl:9) gvsv(main::b) (test_ref.pl:7) rv2sv (test_ref.pl:9) rv2sv (test_ref.pl:7) concat (test_ref.pl:9) concat (test_ref.pl:7) const(PV("\n"\0)) (test_ref.pl:9) const(PV("\n"\0) +) (test_ref.pl:7) concat (test_ref.pl:9) concat (test_ref.pl:7) print (test_ref.pl:9) print b : foo b2 : foo

    So, $$var and ${$var} are the same after optimisation.
    always more than one way to skin an amoebae
    -- MZSanford
      >I, like many programmers, will optimise the smallest code
      >just to eek out the smallest gains. In doing this you
      >learn the art of optimsation.

      I would have to disagree with you on that. The art of optimization is knowing when it's worth optimizing and when it isn't. In my experience, most code isn't worth optimizing. Over-optimizing to save a few microseconds (or less!) is rarely worth it. That said, there are certainly times when you do need to optimize and fixing up a particularly slow (and often used) bit of code (for example, a regex inside a loop) can certainly save the day but writing obscure code to shave off a few microseconds would not classify as "art" in my book.
Re: Efficiency of $$var, ${$var}
by guillaume (Pilgrim) on Aug 20, 2001 at 09:05 UTC
    Ok, I'm not totally sure about that, but I would think it doesn't matter. Each are probably equivalent for perl and considered to be the same at compile-time.

    But if you are considering using a variable as a variable name, you might be interested in reading this:
    Why it's stupid to `use a variable as a variable name'.

    good reading,
    Guillaume
Re: Efficiency of $$var, ${$var}
by stefp (Vicar) on Aug 20, 2001 at 22:16 UTC
    $${a} and $$a compile to the same stuff. The first expressions contains more tokens so it takes longer to parse but you parse it only once (admittedly per script execution) But the real point is that is also more difficult to read.
    # perl -MO=Concise,-exec -e '$$a' 1 <0> enter 2 <;> nextstate(main 1 -e:1) v 3 <$> gvsv(*a) s 4 <1> rv2sv vK/1 5 <@> leave[t1] vKP/REFC -e syntax OK perl -MO=Concise,-exec -e '${$a}' 1 <0> enter 2 <;> nextstate(main 2 -e:1) v 3 <$> gvsv(*a) s 4 <1> rv2sv vK/1 5 <@> leave[t1] vKP/REFC -e syntax OK

    -- stefp