James E Keenan on 14 Jan 2004 03:39:19 -0000 |
On Sun, 11 Jan 2004 22:36:18 -0500, Mark Dominus wrote: > > You never showed us your complete benchmarking code, but here's > what I bet you did: [snip & rearrange] > I don't know that you have 'my @files', because you didn't show us > the complete code. [snip] > Usually, when folks ask this question, we tell them that we can't > help much without seeing the complete code. I might have gotten > Guilty as charged, Mark. But how shall I be punished? Before I walk the plank, let me say a few exculpatory words. When someone posts to a mailing list, s/he is often caught between the Scylla of not posting enough code (to enable readers to solve the problem) and the Charybdis of posting too much (in which case his readers' eyes glaze over before hitting the Reply button and he risks a stern lecture from Tad or a more gentle admonition from someone like myself). It could even be argued that if he knew in advance *exactly* how much code to post, he probably was close to the answer to your question. In this case, I knew the answer was, in a meaningful sense, in my Benchmark call ... so that's what I posted in a good faith effort to escape both Mesdames S and C above. The problem was, that the problem wasn't *just* in my Benchmark call. It was ... well, of course, you guessed it, in: > ? my @files; [snip] > The problem here is that 'Benchmark' uses 'eval' to compile and run > the strings that you supplied as if they were code. But it does > the 'eval' internally, inside of Benchmark.pm, and that is outside > the scope of the '@files' variable, which you declared to be > private to your main file. > Changing the scoping of this variable and @sorted -- and just that correction, nothing more -- solved the problem and made Benchmark work properly in the "code-string" case as it did in the "code-ref" case. our (@files, @sorted); Here is the code and my results: our (@files, @sorted); # [snip population of @files] timethese(10**2, { 'CODE A' => '@sorted = sort {-M $b <=> -M $a} @files;', 'CODE B' => '@sorted = map { $_->[0] } sort {$b->[1] <=> $a->[1]} map {[$_, -M $_]} @files;', 'CODE C' => '$date{$_} = -M $_ for @files; @sorted = sort {$date{$b} <=> $date{$a}} @files; undef %date;', 'CODE D' => '@sorted = map $_->[0], sort {$b->[1] <=> $a->[1]} map [$_, -M $_], @files;', }); No. of files: 466 Benchmark: timing 100 iterations of CODE A, CODE B, CODE C, CODE D... CODE A: 1613 wallclock secs (1613.11 usr + 0.00 sys = 1613.11 CPU) @ 0.06/s CODE B: 229 wallclock secs (228.16 usr + 0.00 sys = 228.16 CPU) @ 0.44/s CODE C: 165 wallclock secs (165.05 usr + 0.00 sys = 165.05 CPU) @ 0.61/s CODE D: 160 wallclock secs (159.94 usr + 0.00 sys = 159.94 CPU) @ 0.63/s In this test, Code C came out substantially better than the block form of the Schwartzian Transform, but the non-block form of the ST came out best of all. Jim Keenan P.S.: This whole thing started when Mark questioned whether the alleged speed advantages of the ST outweighed the opacity of its code. His student at least one contributor to this list argued that it did not. Premature optimization was again denounced. My own 2 cents: If certain stretches of Perl code are known to be sound, reasonably optimized but not transparently "self-documenting," and if you have to re-type that code often enough, then the solution is obvious: throw it into a subroutine ... or a module ... or a CPAN distribution. That's what I did with List::Compare. And today I half wrote a module which does nothing but a functional interface around the Schwartzian Transform. @sorted = sort_by_date(\@files); - **Majordomo list services provided by PANIX <URL:http://www.panix.com>** **To Unsubscribe, send "unsubscribe phl" to majordomo@lists.pm.org**
|
|