Perl 6 small stuff #9½: Perception of speed — benchmarking grep
This is a follow-up to the post Perl 6 small stuff #9: Vantage points and the perception of speed. Here I try to explain what I wanted to with the more or less strange snippet of code I explored there.
The question you may have after reading the last post is: Why generate one million random strings? Well — because I needed a bunch of strings to benchmark grep against. That is to say, explore different methods of filtering an array. Again, I just want to show you how style and choices influence speed.
Let’s first use Perl 5 to get a baseline.
# Perl 5use v5.18;
use Time::HiRes qw( time );<code to generate 1.000.000 array of random strings in here>my $n = time;
say "^yl: " . scalar (grep /^yl/, @e);
say time - $n;'Output:
^yl: 1483
0.0592288970947266 # Time in seconds to execute grep
Naively implemented in Perl 6 — using the same regexp as the Perl 5 variant over — 6 crosses the goal line noticeable slower than its older sibling.
# Perl 6use v6;<code to generate 1.000.000 array of random strings in here>my $n = now; say "^yl: " ~ @e.grep(/^yl/).elems;
say now - $n;'^yl: 1457
3.1745622 # Time in seconds to execute grep
The main culprit is the use of an regex. In P6 we can gain speed by using literal matching instead. In this case we can use the built-in Str method .starts-with:
use v6;<code to generate 1.000.000 array of random strings in here>my $n = now;
say "^yl: " ~ @e.grep( { $_.starts-with("yl") } ).elems;
say now - $n;'Output:
^yl: 1509
1.2343032 # Time in seconds to execute grep
With this change the code is 2,6x faster! But it can become even faster:
use v6;<code to generate 1.000.000 array of random strings in here>my $n = now;
say "^yl: " ~ @e.grep( *.starts-with("yl") ).elems;
say now - $n;'^yl: 1469
0.9462001 # Time in seconds to execute grep
I’ve experienced before that using the “whatever star” (*) is faster than using code blocks matching against $_. I haven’t really looked into why that is, but that change increases the speed improvement overall to 3.4x.
I’d say we’ve reached acceptable speed. But to achieve that I have to live with the fact that as a previous perl 5 user, writing Perl 6 code sometimes feels like optimising something the optimiser usually has done behind the scenes for me. In other words: I have to evolve new habits by forgetting all my bad habits and expectations.
Forget 5, learn 6.
It’s as easy and difficult as that.
