asynchronousasync-awaithhvmhacklang

Hacklang async function seems to be blocking


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:

enter image description here

What am I doing wrong?


Solution

  • 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!