I was using the smart match operator to help generate an array of unique, random numbers. For legacy purposes, I used map in scalar context to do the same thing. Then I saw grep being used in a recent thread in the same manner as my map usage, so I also incorporated that and benchmarked their performances.

Smart match blew the other two away, but what I did find interesting was the resulting difference in the unique arrays generated.

First, to level the playing field for testing, I started with generating a 1_000_000 element array of random numbers to be used as the "pool" that my generator methods would pick against. So, each generator utilized the same pool, rather than another set of random numbers. In the end, it was the generated arrays that were interesting.

Here is a sample of the three unique arrays generated and sorted:

Benchmark: timing 2500 iterations of grepGen, mapGen, smartGen... grepGen: 34 wallclock secs (34.35 usr + 0.00 sys = 34.35 CPU) @ 72 +.78/s (n=2500) mapGen: 14 wallclock secs (14.09 usr + 0.00 sys = 14.09 CPU) @ 17 +7.47/s (n=2500) smartGen: 1 wallclock secs ( 0.95 usr + 0.00 sys = 0.95 CPU) @ 26 +28.81/s (n=2500) Rate grepGen mapGen smartGen grepGen 72.8/s -- -59% -97% mapGen 177/s 144% -- -93% smartGen 2629/s 3512% 1381% -- loop counts - grep: 805000, map: 805000, smart: 495000 array sizes - num: 1000000; grep: 100; map: 100; smart: 100 grep: 1 12 15 18 19 20 21 22 23 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 + 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 + 64 65 66 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 + 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 104 105 106 107 108 +109 110 111 112 113 114 116 117 118 119 map: 1 12 15 18 19 20 21 22 23 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 + 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 + 64 65 66 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 + 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 104 105 106 107 108 +109 110 111 112 113 114 116 117 118 119 smart: 0 1 2 3 5 7 8 9 12 13 15 16 18 19 21 22 23 25 26 27 28 29 30 31 32 33 +34 35 36 37 38 39 42 43 44 45 46 47 48 51 52 53 54 55 56 57 58 59 60 +61 62 63 64 65 66 68 69 70 71 72 73 74 75 76 77 78 79 81 83 84 85 86 +87 89 90 91 92 93 94 95 96 97 98 100 101 102 104 105 106 107 108 109 +110 111 112 113 116 117 118 119

The grep and map arrays are the same, but smart match picked values that the other methods did not! Each method picked from the exact same pool.

This is the curious find that I mentioned in my subject. So, I hope that others can check my code and maybe find the results curious, also.

code

#!/usr/bin/perl use strict; use warnings; use Benchmark qw( timethese cmpthese ); my @doCount = (0); # total loops until unique array generate +d my $range = 120; # numbers range from 0 to $range my $aSize = 1000000; # random pool array size my $uSize = 100; # unique array size my ( @grep, @map, @smart ); my @nums = arrGen(); # generate huge pool of random numbers my $r = timethese( 2500, { grepGen => sub{ @grep = grepGen(); }, mapGen => sub{ @map = mapGen(); }, smartGen => sub{ @smart = smartGen(); }, } ); # show results cmpthese $r; print "loop counts - grep: $doCount[0], map: $doCount[1], smart: $doCo +unt[2]\n"; print "array sizes - num: ", scalar(@nums), # should all == $uSize "; grep: ", scalar(@grep), "; map: ", scalar(@map), "; smart: ", scalar(@smart), "\n"; # show sorted generated arrays to check for a rare duplicate print "grep:\n@{[sortIt(@grep)]}\nmap:\n@{[sortIt(@map)]}\nsmart:\n@{[ +sortIt(@smart)]}\n"; sub arrGen { my @nArray; for ( 1..$aSize ) { my $rInt = int(rand($range)); push @nArray, $rInt; } return @nArray; } sub sortIt { return sort { $a <=> $b } @_; } sub grepGen { my $idx = 0; my @gArray; for ( 1..$uSize ) { $doCount[0]++; my $rInt = $nums[$idx++]; redo if ( @gArray && grep { /$rInt/ } @gArray ); push @gArray, $rInt; } return @gArray; } sub mapGen { my $idx = 0; my @mArray; for ( 1..$uSize ) { $doCount[1]++; my $rInt = $nums[$idx++]; redo if ( @mArray && map { /$rInt/ } @mArray ); push @mArray, $rInt; } return @mArray; } sub smartGen { my $idx = 0; my @sArray; for ( 1..$uSize ) { $doCount[2]++; my $rInt = $nums[$idx++]; redo if ( @sArray && $rInt ~~ @sArray ); push @sArray, $rInt; } return @sArray; }

In reply to Curious find while comparing grep, map, and smart match... by dbuckhal

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.