I have been revisiting Perl recently; it has been more than 10 years since I made my last "serious" attempts at Perl development. Naturally, there is a lot to catch up with - especially the idea of "Modern Perl" as opposed to "Legacy Perl". I must admit that I'm not totally sold on the idea of opposing one with another; however I'm delighted to see that Perl is actively developed. It seems not only to be active but improving as well, and many respectable Perl hackers are advising to move forward to 5.10 and beyond.

Well that sounds very nice, but during my recent encounter with DBD::SQLite I got a new question: is the move worth it? I don't mind all the syntactic sugar - it's all very fine but even Perl 5.005 had it more than enough for me to study and master for another ten years. What I'm actually talking about is speed. We all know that Perl code may not be the best in terms of execution, and usually compare it to C - but what about comparing one version to another? Quick googling wasn't very resultative so I decided to set up a test bench and run some benchmarks on my own.

The script that was used in benchmarks is as follows:

use strict; use warnings; use Benchmark qw(cmpthese); ($_) = <DATA>; chomp; my @data = split /:/; cmpthese(100_000, { 'for-ind-eq' => sub { my @copy = @data; for (0..$#copy) { $copy[$_] = undef if $copy[$_] eq ''; } }, 'for-ind-match' => sub { my @copy = @data; for (0..$#copy) { $copy[$_] = undef if $copy[$_] =~ /^$/; } }, 'foreach-eq' => sub{ my @copy = @data; foreach (@copy) { $_ = undef if $_ eq ''; } }, 'foreach-match' => sub { my @copy = @data; foreach (@copy) { $_ = undef if /^$/; } }, 'map-eq' => sub { my @copy = @data; map { $_ = $_ eq '' ? undef : $_ } @copy; }, 'map-match' => sub { my @copy = @data; map { $_ = /^$/ ? undef : $_ } @copy; }, }); __DATA__ 4479:5509:7721:1743:7821::9119::9532::7095::5028:6179:2693:2133::4158: +7256:7960:::8094:1458:5739:7570:::5059:4926:4933:7378:3066:7916:6062: +::7671:399::::1010::3938:2278:8571:::2286::4740::4133::::2712::::2507 +::1579::4503:3889:1892:7667::::5676::::::8371:2258:372::2795:4126:215 +6:6580:5798:::8138::4545:7843:2231:4414:5792::6187::3488

While I cannot claim to cover all aspects of the language, this simple script does utilize some very basic and widely used language constructs: for/foreach loops, map, array manipulating, scalar comparison and pattern matching. In fact, I used this test script to answer a question that nagged me for ages: what is the best way to check an array of strings for empty strings? While the answer I got was predictable, performance comparison results were not.

I have used four version of Perl for this benchmark: 5.6.1 supplied with Solaris 9 x86 I'm working on (for hysterical raisins) and three custom built versions: 5.8.9, 5.10.1 and 5.14.1. I decided to skip 5.12.3 for I see no reason in testing it now that 5.14.1 is available. All custom builds were Configure'd with -des to ensure genuine vanilla flavor. All Perl versions are unthreaded.

The results are as follows (5.6.1 Benchmark output cut for clarity)

Perl 5.6.1
                 Rate map-match map-eq for-ind-match foreach-match for-ind-eq foreach-eq
map-match     15106/s        --    -8%          -25%          -34%       -36%       -42%
map-eq        16474/s        9%     --          -19%          -28%       -30%       -36%
for-ind-match 20243/s       34%    23%            --          -12%       -14%       -22%
foreach-match 22989/s       52%    40%           14%            --        -3%       -11%
for-ind-eq    23585/s       56%    43%           17%            3%         --        -9%
foreach-eq    25907/s       72%    57%           28%           13%        10%         --

Perl 5.8.9
                 Rate map-match map-eq for-ind-match for-ind-eq foreach-match foreach-eq
map-match     17730/s        --    -5%          -28%       -32%          -40%       -45%
map-eq        18587/s        5%     --          -25%       -29%          -37%       -43%
for-ind-match 24631/s       39%    33%            --        -6%          -17%       -24%
for-ind-eq    26110/s       47%    40%            6%         --          -11%       -20%
foreach-match 29499/s       66%    59%           20%        13%            --        -9%
foreach-eq    32468/s       83%    75%           32%        24%           10%         --

Perl 5.10.1
                 Rate map-match map-eq for-ind-match foreach-match for-ind-eq foreach-eq
map-match     10846/s        --   -10%          -19%          -34%       -39%       -46%
map-eq        12034/s       11%     --          -10%          -26%       -33%       -40%
for-ind-match 13333/s       23%    11%            --          -19%       -26%       -34%
foreach-match 16367/s       51%    36%           23%            --        -9%       -19%
for-ind-eq    17921/s       65%    49%           34%            9%         --       -11%
foreach-eq    20202/s       86%    68%           52%           23%        13%         --

Perl 5.14.1
                 Rate map-match map-eq for-ind-match foreach-match for-ind-eq foreach-eq
map-match     15038/s        --   -14%          -18%          -25%       -48%       -50%
map-eq        17513/s       16%     --           -4%          -13%       -39%       -42%
for-ind-match 18315/s       22%     5%            --           -9%       -36%       -39%
foreach-match 20040/s       33%    14%            9%            --       -30%       -33%
for-ind-eq    28818/s       92%    65%           57%           44%         --        -4%
foreach-eq    29940/s       99%    71%           63%           49%         4%         --

I must admit that I was quite surprised by results; I believe they speak for themselves. I don't know if that is the result of codebase revamping between 5.8 and 5.10, or any other reason; but it seems to me that it's premature to take "Modern Perl is always better" as a given. For some applications, it's not true yet. I do see a strong incentive for upgrade from 5.10.1 to 5.14.1 - the difference is too significant to ignore. As for 5.8.9 to 5.14.1... I'm not sold. Nothing I've seen in perldeltas would suggest that 5.8.9 is now obsolete to the point of being unusable, and this performance hit is very serious reason for me to postpone the upgrade.

All in all, I'd vote for deeper research in this matter. I will do more tests, time permitting. And offer a shy rebellious thought meanwhile: maybe it's worth it to revisit 5.8 and patch it up with the latest bugfixes other than security related?..

Regards,
Alex.

P.S. Coming back to the original question addressed by the benchmark: it is clearly seen that $_ eq '' is usually faster than /^$/. However, /^$/ looks and feels more Perlish - would it be beneficial to check this as a special case with regexp processing and optimize it away?


In reply to Why "Modern Perl" is slower than "Legacy Perl"? by dwalin

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.