I am trying to get an idea of how to implement async (parallel) function call in Perl (in one of my Mojolicious controllers to process lots of data sets).
Here is what I have (a simple example):
use Future::AsyncAwait;
async sub asyncSub{
async sub funcA{
my $num = shift;
print "This is $num (START)\n";
sleep 1;
print "This is $num (END)\n";
};
funcA(1);
funcA(2);
funcA(4);
funcA(5);
funcA(6);
funcA(7);
funcA(8);
funcA(9);
funcA(10);
}
asyncSub();
This code prints out:
This is 1 (START)
This is 1 (END)
This is 2 (START)
This is 2 (END)
This is 4 (START)
This is 4 (END)
This is 5 (START)
This is 5 (END)
This is 6 (START)
This is 6 (END)
This is 7 (START)
This is 7 (END)
This is 8 (START)
This is 8 (END)
This is 9 (START)
This is 9 (END)
This is 10 (START)
This is 10 (END)
It always works synchronously.
Thank you in advance for your help.
Yes indeed. sleep is always synchronous. You did not make any asynchronous calls, so your code isn't asynchronous.
Future::AsyncAwait is not a multi-tasking system. It doesn't provide asynchronousness. Futures are similar to JavaScript promises and even more so to .NET tasks. They provide a means of working with asynchronous calls more easily. But you still have to make asynchronous calls to have asynchronousness.
You'd have the same problem in C# if you used Thread.Sleep( 1000 ) (synchronous) instead of await Task.Delay( 1000 ); (asynchronous).
You will need an async framework to be able to run async code. You mentioned Mojolicious, which itself includes support for async/await. The code below is an example of sleeping using a Mojo::Promise->timer().
I've also included an alternative sub that uses Mojo::IOLoop::Subprocess, which runs in a forked process and can therefore run functions which would otherwise be blocking. However, this has the overhead of starting a new process.
use strict;
use warnings;
use Mojo::Base -async_await;
use Mojo::Promise;
use Mojo::IOLoop::Subprocess;
async sub asyncSub {
my @promises = map { funcA($_) } (1..3);
await Mojo::Promise->all(@promises);
}
async sub funcA {
my $num = shift;
print "This is $num (START)\n";
await Mojo::Promise->timer(1);
print "This is $num (END)\n";
};
async sub funcB {
my $num = shift;
my $subprocess = Mojo::IOLoop::Subprocess->new;
print "Subprocess $num (START)\n";
await $subprocess->run_p( sub {
sleep(1);
});
print "Subprocess $num (END)\n";
return;
};
await asyncSub();
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