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

Last year on the Paris mongers list, someone posted some convincing code showing how much slower (e.g. 25%) using $_ could be, instead of using a lexical. I was going to say as much to a reply to a node I wrote yesterday, but I thought I'd do a benchmark just to be sure.

The results surprise me. To a number of decimal places, there is absolutely no speed difference between these two routines.

#! /usr/bin/perl -w use strict; use Benchmark; my $scratch = '/tmp/foo'; # create a really big file open OUT, ">$scratch" or die "$scratch: $!\n"; print OUT join( "\n", 1..1000000 ), "\n"; close OUT; timethese( shift || 20, { '$_' => sub { my $count = 0; open IN, $scratch or die "$scratch input: $!\n"; while( <IN> ) { chomp; $count += $_; } close IN; }, 'my' => sub { my $count = 0; open IN, $scratch or die "$scratch input: $!\n"; my $rec; while( defined( $rec = <IN> )) { chomp $rec; $count += $rec; } close IN; }, } ); unlink $scratch;

Is there any assumption I'm overlooking? I've looping through a large file, hopefully large enough to avoid OS caching problems. Maybe there's a more pathological example that highlights a speed difference between $_ and a lexical, but I can't find it (and I can't find the original message in my mail archive).

Does anyone know of a case where $_ is slower than a lexical (and no, I'm not talking about local issues). Thanks.

--
g r i n d e r

Replies are listed 'Best First'.
Re: The speed of $_ versus a lexical
by ariels (Curate) on Jul 19, 2001 at 14:14 UTC
    Your code is IO bound (most of the work goes to reading and writing, and even if the file is in memory you have to convert strings to numbers, etc.). Of course you're not going to see any difference between my and implicit operators.

    Try this:

    #!/usr/local/bin/perl -w use strict; use Benchmark; timethese(-2, { default => sub { $_="the quick brown fox"; s/brown/black/ }, my => sub { my $x="the quick brown fox"; $x =~ s/brown/black/ } });
    I get a 2% speed difference; localising $_ makes the `my' version 4% faster.

    Duplicating the string 10_000 times and performing global substitution makes the `my' version 11% faster.

      duh! ok, so I changed the code to the following (by the way, am I the only one interested in playing around with Inline)? :

      #! /usr/bin/perl -w use strict; use Benchmark; my @a = (1..500000); use Inline C => <<'ADDUP_END'; double addup( SV* stub, ... ) { double total = 0; int i; Inline_Stack_Vars; for( i = 0; i < Inline_Stack_Items; ++i ) { total += SvNV(Inline_Stack_Item(i)); } return total; } ADDUP_END timethese shift || 100, { '$_' => sub { my $count = 0; foreach( @a ) { $count += $_; } }, 'my' => sub { my $count = 0; foreach my $var( @a ) { $count += $var; } }, 'Inline' => sub { my $count = addup( @a ); }, };

      now I see around a 7% gain in favour of lexicals (i.e., barely above the noise level). It's not the 25% I was expecting. Heh, the Inline method is close to an order of magnitude faster!

      update: tip o' the hat to Hofmator for spotting an orphan $rec.

      update 2001-08-06: in my travels through the older nodes in the monastery, I encountered another thread that deals with a similar topic: is 'my' that much faster than 'local'?. It may be of interest.

      --
      g r i n d e r
Re: The speed of $_ versus a lexical
by petdance (Parson) on Jul 19, 2001 at 17:13 UTC
    Seems to me that if your code is so speed-critical that you're willing to muck around with benchmarking $_ and a lexical that you should be looking at a much higher level speedup, such as writing the routine in C.

    Prob'ly the best discussion of this sort of analysis is in Jon Bentley's Programming Pearls. It's well worth checking out.

    xoxo,
    Andy
    --
    <megaphone> Throw down the gun and tiara and come out of the float! </megaphone>