Hacklang async function seems to be blocking - asynchronous

I'm learning Hacklang and as a quick test wanted to verify that asynchronous features worked the way I understood them to: that the execution thread would hop over to handle another request while an async operation was in progress.
To test this I wrote this simple index.php:
<?hh
<<__EntryPoint>>
async function main(): Awaitable<void> {
echo "Start sleep<br />\n";
flush();
await \HH\Asio\usleep(10000000);
echo "End sleep\n";
}
Visiting the page in a browser it behaves as you would expect: you immediately see "Start sleep" then 10 seconds later you see "End sleep" appear beneath it.
I then ran a BlazeMeter test to hammer it with 50 requests per second. If the async / await stuff was working properly, it should trivially handle all 50 requests and the requests should have an average response time around 10 seconds. But instead I saw this:
What am I doing wrong?

the execution thread would hop over to handle another request while an async operation was in progress.
This isn't the way async works or what it's for. It's for concurrent data fetching within a single request.
For example, consider this similar program (which I'm directly typing in here as an example and haven't actually spun up HHVM to run, please excuse typos):
<?hh
async function foo(): Awaitable<void> {
// Stand-in for some expensive off-box IO, such as a mysql query.
await \HH\Asio\usleep(10000000);
}
async function bar(): Awaitable<void> {
// Stand-in again.
await \HH\Asio\usleep(10000000);
}
<<__EntryPoint>>
async function main(): Awaitable<void> {
echo "Start sleep<br />\n";
flush();
concurrent {
await foo();
await bar();
}
echo "End sleep\n";
}
Those two sleeps will execute concurrently -- that should take no more time to execute than your original code. This is obviously silly in the case of usleep, but consider if that were a MySQL query, curl request, etc -- something that is a possibly-lengthy bit of IO. We could issue a MySQL request, and while MySQL computes that, we'll swap over to issue a curl request; in the meantime, MySQL has come back, we can finish up with that, and then eventually swap back over to get our now-waiting curl result.
The HHVM documentation on async has a bunch more information, examples, etc. Hopefully with a bit of context the page will make more sense now!

Related

Why Future works after the main function was done?

In the example on dart.dev the Future prints the message after the main function was done.
Why might the Future work after the main function was done? At first glance, after the completion of the main function, the entire work of the program is expected to be completed (and the Future must be cancelled).
The example code:
Future<void> fetchUserOrder() {
// Imagine that this function is fetching user info from another service or database.
return Future.delayed(Duration(seconds: 2), () => print('Large Latte'));
}
void main() {
fetchUserOrder();
print('Fetching user order...');
}
The program prints
Fetching user order...
Large Latte
I've expected just the following
Fetching user order...
This has to do with the nature of futures and asynchronous programming. Behind the scenes, Dart manages something called the asynchronous queue. When you initiate a future (either manually like you did with Future.delayed or implicitly by calling a method marked async, that function's execution goes into the queue whenever its execution gets deferred. Every cycle when Dart's main thread is idle, it checks the futures in the queue to see if any of them are no longer blocked, and if so, it resumes their execution.
A Dart program will not terminate while futures are in the queue. It will wait for all of them to either complete or error out.

Why Async.StartChild does not take CancellationToken?

I am struggling to understand Async.[StartChild|Start] API design.
What I would like is to start an async process which does some tcp stream reading and calling a callback according to commands arriving on tcp.
As this async process does not really return any single value, it seems like I should use Async.Start. At some point I want to "close" my tcp client and `Async.Start takes CancellationToken, which gives me ability to implement 'close". So far so good.
The problem is, I would like to know when tcp client is done with cancellation. There is some buffer flushing work done, once Cancel is requested, so I do not want to terminate application before tcp client is done cleanup. But Async.Start returns unit, which means I have no way of knowing when such async process is complete. So, looks like Async.StartChild should help. I should be able to invoke cancellation, and when cleanup is done, this async will invoke next contiuation in chain (or throw an exception?). But... Async.StartChild does not take CancellationToken, only timeout.
Why Async.StartChild implements just single case of cancellation strategy (timeout) instead of exposing more generic way (accept CancellationToken)?
To answer the first part of the question - if you need to do some cleanup work, you can just put it in finally and it will be called when the workflow is cancelled. For example:
let work =
async {
try
printfn "first work"
do! Async.Sleep 1000
printfn "second work"
finally
printfn "cleanup" }
Say you run this using Async.Start, wait for 500ms and then cancel the computation:
let cts = new System.Threading.CancellationTokenSource()
Async.Start(work, cts.Token)
System.Threading.Thread.Sleep(500)
cts.Cancel()
The output will be "first work, cleanup". As you can see, cancelling the computation will run all the finally clauses.
To answer the second part of the question - if you need to wait until the work completes, you can use RunSynchronously (but then, perhaps you do not actually need asynchronous workflows, if you are blocking anyway...).
The following starts a background process that cancels the main work after 500ms and then starts the main work synchronously:
let cts = new System.Threading.CancellationTokenSource()
async {
do! Async.Sleep(500)
cts.Cancel() } |> Async.Start
try Async.RunSynchronously(work, cancellationToken=cts.Token)
with :? System.OperationCanceledException -> ()
printfn "completed"
This prints "first work, cleanup, completed" - as you can see, the RunSynchronously call was blocked until the work was cancelled.

Meteor wrapAsync works, but restarts server after completion

I'm trying to learn how to use Meteor's wrapAsync helper. I want to use it to call an async function sequentially (not simultaneously). Though my code works, when it completes, the server restarts, which makes me wonder if there is a bug in my code. Unfortunately, there is no message saying why it restarted. Am I missing something?
The code is below and also on my MeteorPad demo.
var doAsyncIO = function (num, callback) {
setTimeout( function () {
// wrapAsync will use the following callback as the basis of returning results synchronously
callback(null, 'This is delayed result #' + num ); // nodeJS form: cb(error,result)
}, 2500); // wait 2.5 seconds before returning result
};
// Now create a synchronous version of doAsyncIO that sleeps, not blocks
// so that the CPU can do other tasks while waiting for the result
var doSyncIO = Meteor.wrapAsync(doAsyncIO);
// Now call doSyncIO twice sequentially (not simultaneously)
console.log('\n*** Starting first call to doSyncIO');
var result1 = doSyncIO(1);
console.log('result1:', result1);
// The following block runs after result1 is set (which is what I want)
console.log('\n*** Starting second call to doSyncIO');
var result2 = doSyncIO(2);
console.log('result2:', result2);
After a code change and after the console logs appear on the terminal, the terminal says the server restarts with no reason provided which makes me wonder if there is a bug in my code!
2015-04-19 Update: the restart message may not actually indicate a problem since it only shows up after a code change. Perhaps it's simply the standard restart message. Nevertheless, it seems like the restart message should really occur before the console logs.
Feel free to comment or fork my MeteorPad demo though to see if it's something else.

async/await in background in ASP.NET WebApi

Let's suppose i have the following async method that needs fairly long time until completing its work:
void async Task LongWork()
{
await LONGWORK() // ... long work
}
Now, in an web api, i would like to run that work in a background (i.e., i want to return the Http Request after starting that LongWork() but before its completion:
I can think of three approaches to achieve this:
1) public async Task<string> WebApi()
{
... // do another work
await Task.Factory.StartNew(() => LongWork());
return "ok";
}
2) public async Task<string> WebApi()
{
... // do another work
await Task.Factory.StartNew(async () => await LongWork());
return "ok";
}
3) public async Task<string> WebApi()
{
... // do another work
Task.Factory.StartNew(async () => await LongWork());
return "ok";
}
Q1: What's the difference between approach #1 and #2?
Q2: What is the right way to, in the ASP.NET world, run a method (in this example, LongWork() containing some async/await pairs in a background thread?
In particular, in #3, there's no "await" before Task.Factory.StartNew(async () => await LongWork()). Is it fine?
Thanks!
Q1: What's the difference between approach #1 and #2?
#1 has less overhead. That is the only difference.
Q2: What is the right way to, in the ASP.NET world, run a method (in this example, LongWork() containing some async/await pairs in a background thread?
None of the options you provided. For one thing, they all use Task.Factory.StartNew without specifying a TaskScheduler, which is dangerous (as I describe on my blog). They should use Task.Run instead. However, even if you use Task.Run, you will run into a more serious underlying problem.
The underlying problem is this: the HTTP protocol is centered around each request having exactly one matching response. When an HTTP server (such as ASP.NET) knows that there are no outstanding requests, it will make assumptions like "it's safe to recycle the worker process".
I describe this problem in more detail on my blog. Also in that blog post is a type BackgroundTaskManager that registers background tasks with the ASP.NET runtime and (correctly) executes them via Task.Run. You should only use BackgroundTaskManager if you read the blog post and understand and accept that this is still dangerous and unsafe.
A far better (read: more reliable) solution is to first write out a representation of the work to be done to persistent storage (e.g., an Azure queue) and have an independent backend process (e.g., an Azure worker role) that processes requests from the queue.

async CTP: I am doing something wrong, the GUI is blocked

I am making some probes with async CTP but I don't get a good result, because the GUI is blocked.
I have an WPF application with a button and a textBox for a log. Then I have this code:
private async void btnAsync01_Click(object sender, RoutedEventArgs e)
{
UpdateTxtLog("Enter in Button Async01: " + System.DateTime.Now);
await metodo01Async();
UpdateTxtLog("Exit button Async01: " + System.DateTime.Now);
}
private async Task slowMethodAsync()
{
UpdateTxtLog("Enter in slowMethod: " + System.DateTime.Now);
Thread.Sleep(5000);
UpdateTxtLog("Exit slowMethod: " + System.DateTime.Now);
}
If am not wrong, set a method with "sync" (click event in this case), it let the method use the await, to return the point to execution to the method which call the actual method, then the execution return to the GUI.
So in the GUI,I click the button, then in the click event await to the slowMethod, how I use await with the slowMethod the control should be returned to the GUI, and then the GUI should not be blocked. However, the GUI is blocked and the txtLog not show any information until slowMethod finish.
Is this because slowMethod is executed in the same thread than the GUI? If I am wrong, with async normally use the same thread than the method which call the await method, but I think that the reason of the async avoid this.
How can I simulate an slowMethod without thread.Sleep? Perhaps this is the problem, because in slowMethod I sleep the thread, and the thread of slowMethod is the same than the GUI.
This makes me think that is always recommended execute in other thread the code of the async methods? If this is correct, which is the sense to use async if also I need to use task for not blocking the main thread?
When to use async and when to use tasks?
For this probes, I am following the examples in this web: http://www.codeproject.com/Articles/127291/C-5-0-vNext-New-Asynchronous-Pattern
In this example, it's used client.DownloadStringTaskAsync as slowMethod, but in my case, instead of using a WebClient, I use a dummy method, with a sleep to simulate a slowMethod. I think that is the unique difference.
Thanks.
Daimroc.
Simulate waits using await TaskEx.Delay(5000), which executes an asynchronous sleep/delay.
You may also want to read up some more on async/await. There are several good Channel9 videos; Stephen Toub, Eric Lippert, and many other Microsoft bloggers have excellent overviews. Jon Skeet's "eduasync" blog series is also good for really going deep. I've written up an async intro on my own blog, as have many others.
Here's how async and await really work, in a nutshell:
The async keyword only enables the await keyword. That is all. It does not run the method on a background thread.
await only acts asynchronously if its "awaiter" is not completed.
So in your case, btnAsync01_Click and slowMethodAsync both run on the UI thread. slowMethodAsync will run synchronously (executing Thread.Sleep), and then return to btnAsync01_Click, which awaits the already-completed task. Since the task is already completed, btnAsync01_Click just continues executing without yielding to the UI message loop.
If you replace Thread.Sleep with await TaskEx.Delay, then btnAsync01_Click will start running on the UI thread, and will call slowMethodAsync (also running on the UI thread). When slowMethodAsync awaits the delay (which is not completed), it will return an incomplete task to btnAsync01_Click. btnAsync01_Click will await that task (which is not completed), and will return to the UI loop.
When the delay expires, it will complete, and slowMethodAsync will resume (on the UI thread). When slowMethodAsync completes, its returned task will complete, and btnAsync01_Click will resume (on the UI thread).

Resources