http://www.perlmonks.org?node_id=1216384


in reply to Re^2: (Easy Perl concurrency with MCE)
in thread Why should any one use/learn Perl 6?

You sure as hell don't need Cuckoo, errr, notPerl "6", or anything other than Perl to write clean, fast, correct, parallel code that can be used today in performance-critical environments, aka Real Life.

Why can't you just be positive? Always so negative!

I hadn't heard about MCE yet. By the looks of it, it has taken the ideas I had when I implemented the forks and ThreadPool modules to the next level. Kudos to Mario Roy.

Now to get back to your example, but then in Perl 6:

use MyClient; my $client = MyClient.new; my $list = $client.call('ListCustomers'); $list.parse_json_payload; say "Start: Found $list.payload.totalCount() accounts"; my %results; for $list.payload.items -> $account { my $id = $account.id; say "Deleting $id"; my $call = $client->call('DeleteCustomer', account_id => $id); say 'Status: ' . $call.status; $call.status == 204 ?? %results<OK>++ !! %results<NOT_OK>++; } say "Results: %results.perl()"

To make this run on multiple CPU's, one basically needs to do only one thing: prefix the for with a hyper;

hyper for $list.payload.items -> $account {

There is however one caveat: hashes in Perl 6 are not thread safe in the sense that they might lose updates when being updated from multiple threads. If you're just interested in number of successes / fails, why not make it two counters instead of elements in a hash? When updating integers from multiple threads, you should use atomic integers (otherwise you would have the same problem as with the hash elements). So the code becomes:

use MyClient; my $client = MyClient.new; my $list = $client.call('ListCustomers'); $list.parse_json_payload; say "Start: Found $list.payload.totalCount() accounts"; my atomicint $ok; my atomicint $not-ok; hyper for $list.payload.items -> $account { my $id = $account.id; say "Deleting $id"; my $call = $client->call('DeleteCustomer', account_id => $id); say 'Status: ' . $call.status; $call.status == 204 ?? atomic-inc-fetch($ok) !! atomic-inc-fetch($ +not-ok) } say "Results: ok = $ok, not-ok = $not-ok"

I've used the ASCII equivalent of the atomic increment operator, since PerlMonks does not display the unicode equivalent "++⚛️" inside code blocks properly.

So I would argue three things here:

  1. Perl 6 has less boilerplate to begin with (no use statements needed)
  2. Perl 6 needs less boilerplate to parallelize (just adding "hyper" will do in many cases
  3. Some thought needs to go into updating data structures from multiple threads at the same time

Note that the Perl 5 solution to updating shared data structures requires tieing and locking, neither of which is good for performance. The Perl 6 solution using atomic increment is lockless and uses hardware features of the CPU.

Hope this clarifies.

EDIT: fixed $results{} -> %results<> non-migrato, haj++