Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React uses a single thread when processing a channel

My intention is to have different threads reading simultaneously from a single channel, and processing things asynchronously. I thought this would do the trick:

my Channel $KXGA .= new;

for ^100 {
    $KXGA.send( (100000..200000).pick );
}

my $sums = start react whenever $KXGA -> $number {
    say "In thread ", $*THREAD.id;
    say "→ ", (^$number).sum;
}

(this hangs up because I'm not closing the channel, but please don't look at that). This outputs, whatever I do:

In thread 4
→ 6995966328
In thread 4
→ 12323793510
In thread 4
→ 5473561506

So it's always using a single thread and processing things sequentially, and not in parallel. Is there some way of doing that? Even if I start the thread within the whenever block, the result will be exactly the same...

like image 558
jjmerelo Avatar asked Mar 30 '18 16:03

jjmerelo


1 Answers

The react/whenever construct is intended for processing one message at a time and in full. The point is that state held within the react block is safe thanks to this.

It's possible to have multiple workers reading from a Channel; they'll just need setting up as follows:

my @sums;
for ^4 {
    push @sums, start react whenever $KXGA -> $number {
        say "In thread ", $*THREAD.id;
        say "→ ", (^$number).sum;
    }
}

This react approach, when used with use v6.d.PREVIEW, has the advantage that when there's less work, it won't actually occupy 4 threads at all, and they can get on with other pooled work. If instead the whole application is just processing stuff from the Channel and that's all, you'll have less overhead and better locality with just:

my @sums;
for ^4 {
    push @sums, start for $KXGA.list -> $number {
        say "In thread ", $*THREAD.id;
        say "→ ", (^$number).sum;
    }
}

Unlike with react there's no opportunity to react to different data sources in this approach (the reason Channels work with react is primarily so you can consume them and simultaneously work with async data sources too, or perhaps deal with multiple channels at once). But if you don't need to, then the for way is a tad simpler in the code and is almost certainly faster (and, as with react, the loops compete over the items in the Channel and terminate gracefully when it is closed).

like image 166
Jonathan Worthington Avatar answered Nov 09 '22 16:11

Jonathan Worthington