Consider the following Perl 6 script skeleton:
my regex perlish { .*[ea]?[ui]? rl $ }
my Str @words = '/usr/share/dict/words'.IO.lines;
for @words -> $word {
...
}
base idea for the code in this question from the perl6 website's examples.
My /usr/share/dict/words
is an indirect symbolic link to /usr/share/dict/american-english
. It's 99,171 lines long, with one word/line.
For comparison's sake, Python 3 does 100 loops of the below in a total of 32 seconds: that's just 0.32942s / loop.1
Here are the things I've tried putting in place of the stub code, with their benchmark times as noted:
"Inline" if
— 100 loops, average 9.74219s / loop, totalling 16 min 14.219s
say "$word probably rhymes with Perl" if $word ~~ /<perlish>/;
say "$word is a palindrome" if $word eq $word.flip && $word.chars > 1;
Short Circuit (not ternary) — 10 loops, average 6.1925s / loop, normalised to totalling +/- 10.3 min
$word eq $word.flip && $word.chars > 1 && say "$word is a palindrome";
$word ~~ /<perlish>/ && say "$word probably rhymes with Perl";
given/when
(switch/case
) — 100 loops, average 6.18568s / loop totalling 10 min 18.568s
given $word {
when /<perlish>/
{ say "$word probably rhymes with Perl"; proceed; }
when $word eq $word.flip && $word.chars > 1
{ say "$word is a palindrome"; proceed; }
}
"normal" if
block — 100 loops, average 6.0588s / loop totalling 10 min 5.880s
if $word eq $word.flip && $word.chars > 1 { say "$word is a palindrome"; }
if $word ~~ /<perlish>/ { say "$word probably rhymes with Perl"; }
Somewhat unsurprisingly, the normal if block is fastest. But, why is the inline if
(what the website uses for an example) so much slower?
1 I'm not saying Perl 6 is slow... but I thought Python was slow and... wow. Perl 6 is slow... ignoring multithreading, parallelism and concurrency, all of which are built in by Perl 6 and which Python leaves much to be desired.
Specs: Rakudo version 2015.12-219-gd67cb03 on MoarVM version 2015.12-29-g8079ca5 implementing Perl 6.c
on a
2.2GHz QuadCore Intel Mobile i7 with 6GB of RAM.
I ran the tests like time for i in ``seq 0 100``; do perl6 --optimize=3 words.pl6; done
.
(This page became the p6doc Performance page.)
I don't know why the statement modifier form of if
is slower. But I can share things that can help folk deal with Perl 6 speed issues in general so I'll write about those, listed easiest first. (I mean easiest things for users and potential users to do, not easiest for compiler devs.)
Why does the speed of your code matter?
I recommend you share your answer to these higher level questions:
How much faster would your code need to run to make a worthwhile difference? Could the full speed up wait another month? Another year?
Are you exploring Perl 6 for fun, assessing its potential long term professional relevance to you, and/or using it in your $dayjob?
Wait for Rakudo to speed up
5 years ago Rakudo was 1,000 times slower or more for some operations. It's been significantly speeding up every year for years even though speeding it up was explicitly not the #1 dev priority. (The mantra has been "make it work, make it work right, make it fast". 2016 is the first year in which the "make it work fast" aspect is truly in the spotlight.)
So, imo, one sensible option if the Rakudo Perl 6 compiler is really too slow for what you want to do, is to wait for others to make it faster for you. It could make sense to wait for the next official release (there's at least several each year) or wait a year or three depending on what you're looking for.
Visit the freenode IRC channel #perl6
Compiler devs, the folk who best know how to speed up Perl 6 code, aren't answering SO questions. But they are generally responsive on #perl6.
If you don't get all the details or results you want from here then your best bet is to join the freenode IRC channel #perl6 and post your code and timings. (See next two headings for how best to do that.)
Profile code snippets
Rakudo on MoarVM has a built in profiler:
$ perl6 --profile -e 'say 1'
1
Writing profiler output to profile-1453879610.91951.html
The --profile
option is currently only for micro-analysis -- the output from anything beyond a tiny bit of code will bring your browser to its knees. But it could be used to compare profiles of simple snippets using if
conventionally vs as a statement modifier. (Your regex using examples are almost certainly too complex for the current profiler.)
Profiling results may well mean little to you without help and/or may point to confusing internal stuff. If so, please visit #perl6.
Write faster Perl 6 code, line by line
Your immediate focus seems to be the question of why one way of writing a line of code is slower than another way. But the flipside of this "academic" question is the practical one of writing faster lines of code.
But if someone's a Perl 6 newbie, how are they going to know how? Asking here is one way but the recommended approach is visiting #perl6 and letting folk know what you want.
#perl6 has on-channel evalbots that help you and others investigate your issue together. To try code snippets out publicly enter m: your code goes here
. To do so privately write /msg camelia m: your code goes here
.
For simple timing use variations on the idiom now - INIT now
. You can also generate and share --profile
results easily using a #perl6 evalbot. Just join the channel and enter prof-m: your code goes here
.
Write faster Perl 6 code by refactoring
Use better algorithms, especially parallel/concurrent ones.
Use native arrays (eg Array[int8]
for an array of 8 bit integers) for compact, faster number crunching.
For more info about doing this, visit #perl6.
Use (faster) foreign code
Use NativeCall wrappers for C libs such as Gumbo or for C++ libs (experimental). NativeCall itself is currently poorly optimized but that's set to change in 2016 and for many applications the NativeCall overhead is a small part of performance anyway.
Inline::Perl5 builds on NativeCall to enable use of Perl 5 in Perl 6 (and vice-versa) including arbitrary Perl 5 code and high-performance Perl 5 XS modules. This interop allows passing integers, strings, arrays, hashes, code references, file handles and objects between Perl 5 and Perl 6; calling methods on Perl 5 objects from Perl 6 and calling methods on Perl 6 objects from Perl 5; and subclassing Perl 5 classes in Perl 6.
(There are similar but less mature or even alpha variants for other langs like Inline::Python, Inline::Lua and Inline::Ruby.)
Review benchmarks
The best relevant benchmarking tool I know of is perl6-bench which compares various versions of Perl with each other including various versions of both Perl 5 and Perl 6.
There may already be benchmarks contrasting a regular if
statement and a statement modifier form if
statement but I doubt it. (And if not, you would be making a nice contribution to Perl 6 if you wrote an extremely simple pair of snippets and got them added to perl6-bench.)
Help speed Rakudo up
The Rakudo Perl 6 compiler is largely written in Perl 6. So if you can write Perl 6, then you can hack on the compiler, including optimizing any of the large body of existing high-level code that impacts the speed of your code.
Most of the rest of the compiler is written in a small language called NQP that's almost just a subset of Perl 6. So if you can write Perl 6 you can fairly easily learn to use and improve the middle-level NQP code too.
Finally, if low-level C hacking is your idea of fun, checkout MoarVM.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With