Given some code which does a bit of math/casting for each number from 1 to 500000, we have options:
Simple for loop:
for ^500000 -> $i { my $result = ($i ** 2).Str; }. In my unscientific benchmark, this takes 2.8 seconds.The most canonical parallel version does each bit of work in a
Promise, then waits for the result.await do for ^500000 -> $i { start { my $result = ($i ** 2).Str; } }takes 19 seconds. This is slow! Creating a new promise must have too much overhead to be worthwhile for such a simple computation.Using a parallel
mapoperation is fairly fast. At 2.0 seconds, the operation seems barely slow enough to take advantage of parallelization:(^500000).race.map: -> $i { my $result = ($i ** 2).Str; }
The third option seems best. Unfortunately, it reads like a hack. We should not be writing map code for iteration in sink context, because others that read "map" in the source may assume the purpose is to build a list, which isn't our intent at all. It's poor communication to use map this way.
Is there any canonical fast way to use Perl 6's built in concurrency? A hyper operator would be perfect if it could accept a block instead of only functions:
(^500000)».(-> $i { my $result = ($i ** 2).Str; }) # No such method 'CALL-ME' for invocant of type 'Int'