Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

Tribute to TMTOWTDI

by s0ttle (Scribe)
on Oct 22, 2001 at 16:33 UTC ( [id://120503]=perlmeditation: print w/replies, xml ) Need Help??

There is more than one way to do a specific task in Perl which is one of the many facets of Perl. That said, I was tinkering around with perl on my slackware box and I got the idea to see how many different ways I could use the same function to do the same task.

I wonder if there is any performance/compilation difference between using any of the below.
#!/usr/bin/perl -w use strict; my (@a,@b); @a = ('a'..'z'); @b = map uc,@a; print @b,"\n"; @b = map uc $_,@a; print @b,"\n"; @b = map uc(),@a; print @b,"\n"; @b = map uc($_),@a; print @b,"\n"; @b = map {uc} @a; print @b,"\n"; @b = map {uc $_} @a; print @b,"\n"; @b = map {uc()} @a; print @b,"\n"; @b = map {uc($_)} @a; print @b,"\n";
Yes, I know I can avoid using map:
perl -e '@a = (a..z); print uc for(a..z);'

Edit kudra, 2001-10-23 Removed font tags per ntc request

Replies are listed 'Best First'.
Re: Tribute to TMTOWTDI
by andreychek (Parson) on Oct 22, 2001 at 17:08 UTC
      I wonder if there is any performance/compilation difference between using any of the below.

    Interesting question, lets find out. I used Benchmark to figure this out. I ran them through at 50,000 iterations, and I changed all the "print" statements to "warn" statements, so I could pipe STDERR to /dev/null, and still see the results of the benchmark on STDOUT. Here's the code:
    #!/usr/bin/perl -w use strict; use Benchmark; use vars qw/ @a @b /; @a = ('a'..'z'); timethese(50000, { '1' => '@b = map uc,@a; warn @b,"\n"', '2' => '@b = map uc $_,@a; warn @b,"\n"', '3' => '@b = map uc(),@a; warn @b,"\n"', '4' => '@b = map uc($_),@a; warn @b,"\n"', '5' => '@b = map {uc} @a; warn @b,"\n"', '6' => '@b = map {uc $_} @a; warn @b,"\n"', '7' => '@b = map {uc()} @a; warn @b,"\n"', '8' => '@b = map {uc($_)} @a; warn @b,"\n"', });
    And here are the results:
    Benchmark: timing 50000 iterations of 1, 2, 3, 4, 5, 6, 7, 8... 1: 4 wallclock secs ( 4.55 usr + 0.03 sys = 4.58 CPU) @ 10917.03/s +(n=50000) 2: 5 wallclock secs ( 4.51 usr + 0.03 sys = 4.54 CPU) @ 11013.22/s +(n=50000) 3: 5 wallclock secs ( 4.53 usr + 0.03 sys = 4.56 CPU) @ 10964.91/s +(n=50000) 4: 4 wallclock secs ( 4.54 usr + 0.03 sys = 4.57 CPU) @ 10940.92/s +(n=50000) 5: 5 wallclock secs ( 4.52 usr + 0.06 sys = 4.58 CPU) @ 10917.03/s +(n=50000) 6: 5 wallclock secs ( 4.52 usr + 0.00 sys = 4.52 CPU) @ 11061.95/s +(n=50000) 7: 4 wallclock secs ( 4.34 usr + 0.01 sys = 4.35 CPU) @ 11494.25/s +(n=50000) 8: 5 wallclock secs ( 4.31 usr + 0.04 sys = 4.35 CPU) @ 11494.25/s +(n=50000)
    While these results show #7 and #8 as being the fastest, I would consider this inconclusive. The fact is, it's so close that every time I run this test, I keep getting wide ranging answers, even with 50,000 iterations.

    Either way, it was still fun :-)
    -Eric

    Updated: Fixed a booboo pointed out by chipmunk. The benchmark actually runs correctly now :-)
      Unfortunately, piping STDERR to /dev/null hid the key mistake in this benchmark. You have declared @a and @b as lexical variables, and passed the code snippets to Benchmark as strings. The eval of the code snippets occurs within Benchmark, where the lexical @a and @b are not in scope. Thus, all of the code snippets are iterating over an empty array! The difference in execution time that you saw is just noise.

      To avoid this problem, you should either declare @a and @b as global variables or pass the code snippets as anonymous subroutine references.

      Here's an improved benchmark:

      #!/usr/bin/perl -w use 5.006; use strict; use Benchmark qw/ cmpthese /; use vars qw/ @a @b /; @a = ('a'..'z'); cmpthese(-3, { '1' => '@b = map uc,@a', '2' => '@b = map uc $_,@a', '3' => '@b = map uc(),@a', '4' => '@b = map uc($_),@a', '5' => '@b = map {uc} @a', '6' => '@b = map {uc $_} @a', '7' => '@b = map {uc()} @a', '8' => '@b = map {uc($_)} @a', }); __END__ Benchmark: running 1, 2, 3, 4, 5, 6, 7, 8, each for at least 3 CPU sec +onds... 1: 4 wallclock secs ( 3.17 usr + 0.01 sys = 3.18 CPU) @ 97 +06.92/s (n=30868) 2: 4 wallclock secs ( 3.18 usr + 0.02 sys = 3.20 CPU) @ 97 +10.31/s (n=31073) 3: 4 wallclock secs ( 3.13 usr + 0.02 sys = 3.15 CPU) @ 97 +73.02/s (n=30785) 4: 4 wallclock secs ( 3.13 usr + 0.01 sys = 3.14 CPU) @ 98 +98.09/s (n=31080) 5: 3 wallclock secs ( 3.17 usr + 0.00 sys = 3.17 CPU) @ 96 +11.67/s (n=30469) 6: 3 wallclock secs ( 3.18 usr + 0.01 sys = 3.19 CPU) @ 96 +50.47/s (n=30785) 7: 4 wallclock secs ( 3.04 usr + 0.02 sys = 3.06 CPU) @ 95 +82.68/s (n=29323) 8: 4 wallclock secs ( 3.32 usr + 0.01 sys = 3.33 CPU) @ 95 +33.33/s (n=31746) Rate 8 7 5 6 1 2 3 4 8 9533/s -- -1% -1% -1% -2% -2% -2% -4% 7 9583/s 1% -- -0% -1% -1% -1% -2% -3% 5 9612/s 1% 0% -- -0% -1% -1% -2% -3% 6 9650/s 1% 1% 0% -- -1% -1% -1% -3% 1 9707/s 2% 1% 1% 1% -- -0% -1% -2% 2 9710/s 2% 1% 1% 1% 0% -- -1% -2% 3 9773/s 3% 2% 2% 1% 1% 1% -- -1% 4 9898/s 4% 3% 3% 3% 2% 2% 1% --
      The difference between the solutions is still insignificant. With repeated benchmarks, the order of the solutions will change, and the percentage differences will remain small.
        Update
        This node was written partially because I didn't grok the point that chipmunk was making, but I believe it still serves as a useful clarification of the quote below. The important point here is that chipmunk is talking about the Benchmark _file_ and not package. See the follow ups for some interesting implications of this subtle difference. Also I have removed the later portion of the quoted sentence 'where the lexical @a and @b are not in scope ' because it appears I am discussing the lexical variables, whereas I am not. My apologies.
        End Update

        The eval of the code snippets occurs within Benchmark,

        Actually, this isn't correct. Benchmark goes through some interesting (not necessarily completely correct either)contortions to execute code from the package it was called from, in this case main.

        This can be seen from this snippet from Benchmark::runloop which is the primary timing routine in Benchmark. (BTW, i only know this cause ive been working on a OO version of Benchmark, coming Real Soon Now to the Code Catacombs :-)

        # find package of caller so we can execute code there my($curpack) = caller(0); my($i, $pack)= 0; while (($pack) = caller(++$i)) { last if $pack ne $curpack; } my ($subcode, $subref); if (ref $c eq 'CODE') { $subcode = "sub { for (1 .. $n) { local \$_; package $pack; &\$c; +} }"; $subref = eval $subcode; } else { $subcode = "sub { for (1 .. $n) { local \$_; package $pack; $c;} } +"; $subref = _doeval($subcode); }
        Oh and a note to andreychek I dont think that including print,warn statements in a benchmark (unless warn() is what you are benchmarking) is a good idea. The overhead of them executing probably drowns out the difference between the functions. Yves / DeMerphq
        --
        Have you registered your Name Space?
Re: Tribute to TMTOWTDI
by jeroenes (Priest) on Oct 22, 2001 at 17:51 UTC
    These functions deparse to two different lines:
    @b = map(uc($_), @a); print @b, "\n"; @b = map(uc($_), @a); print @b, "\n"; @b = map(uc($_), @a); print @b, "\n"; @b = map(uc($_), @a); print @b, "\n"; @b = map({uc $_;} @a); print @b, "\n"; @b = map({uc $_;} @a); print @b, "\n"; @b = map({uc $_;} @a); print @b, "\n"; @b = map({uc $_;} @a); print @b, "\n";
    But these probably are interpreted in a next stage to exactly the same internally. So that's probably why the other people in this thread didn't find any realy difference with BenchMark.

    Jeroen
    "We are not alone"(FZ)

Re: Tribute to TMTOWTDI
by iakobski (Pilgrim) on Oct 22, 2001 at 17:05 UTC
    use Benchmark and then you won't need to wonder any more.

    -- iakobski

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others about the Monastery: (4)
As of 2024-03-29 08:05 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found