使用hack的异步/等待(async/await)来执行异步处理
PHP可以通过HHVM来进行高速执行,但通过使用hack编写程序可以获得更多的好处。
其中特别重要的是利用async/await实现异步处理。
以下是从官方手册中摘录出来的这种方法的优点。
来源
-异步/介绍
Async是什么
Hack提供了一种可以从程序中使用的协作式多任务功能。通过在代码中使用async机制,可以隐藏输入/输出(I/O)延迟和数据获取处理。如果代码中包含等待网络访问或数据库查询的处理,async可以通过执行与输入/输出无关的其他处理来将等待时间最小化。
async不是多线程。HHVM将执行PHP/Hack代码在一个主请求线程中。但是,其他处理,如MySQL查询,可以在不使用代码执行时间的情况下进行执行。
限制
-
- 全ての PHP/HAck コードはメインリクエストスレッドで実行される。
- ブロッキングなAPI (例 mysql_query(), sleep()) は自動的に非同期な処理に変換されません。 これはそれぞれの実行順序が変わる事によって予期しない影響が起こることが安全ではない為です。
异步的例子:cURL
不使用异步方法,进行两个cURL请求将如下所示。
<?hh
namespace Hack\UserDocumentation\Async\Intro\Examples\NonAsyncCurl;
function curl_A(): mixed {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://example.com/");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
return curl_exec($ch);
}
function curl_B(): mixed {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://example.net/");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
return curl_exec($ch);
}
function main(): void {
$start = microtime(true);
$a = curl_A();
$b = curl_B();
$end = microtime(true);
echo "Total time taken: " . strval($end - $start) . " seconds" . PHP_EOL;
}
main();
总共花费时间:1.050155878067秒
– 在3v4l.org网站上的执行示例
在上述的例子中,curl_A()内部的curl_exec()会阻塞所有的操作。因此,即使curl_B()是独立于curl_A()的处理,也会等待curl_A()的处理完成后才会被执行。
幸运的是,HHVM提供了curl_exec()的异步版本。
<?hh
namespace Hack\UserDocumentation\Async\Intro\Examples\Curl;
async function curl_A(): Awaitable<string> {
$x = await \HH\Asio\curl_exec("http://example.com/");
return $x;
}
async function curl_B(): Awaitable<string> {
$y = await \HH\Asio\curl_exec("http://example.net/");
return $y;
}
async function async_curl(): Awaitable<void> {
$start = microtime(true);
list($a, $b) = await \HH\Asio\v(array(curl_A(), curl_B()));
$end = microtime(true);
echo "Total time taken: " . strval($end - $start) . " seconds" . PHP_EOL;
}
\HH\Asio\join(async_curl());
总共花费时间:0.74790596961975秒
– 在3v4l.org的示例程序
非同期版本的curl_exec()允许在等待cURL响应期间执行调度程序中的其他代码。在这种情况下,将异步执行curl_B()。当调度程序执行处理时,将执行另一个异步的curl_exec()。由于HTTP请求较演算处理较慢,主线程将处于空闲状态,直到请求完成为止。
执行顺序通常会像上述一样,但也有可能不是这样的。例如,如果curl_B()的请求比curl_A()的HTTP要快得多,那么curl_B()的处理可能会在curl_A()处理完成之前完成。
通过异步处理来提高速度的好处受到网络状态的影响,例如DNS缓存等是多变的。但是它可能带来戏剧性的效果。
将以下内容用中文进行翻译,只需要给出一种选择:
总结
HHVMを使ってコードを実行する場合、入出力に関する部分だけでもhackを使って書き換える事で非同期処理を実現する事ができます。リモートのWEBAPIコールやデータベースの処理を順次実行するようなアプリケーションの場合は大幅な高速化を実現できる可能性があります。
非同期処理をPHPで実現する為に複雑なバックエンドを構築する必要がある場合は、HHVMの備える非同期処理の利用も検討してみるとよいのではないでしょうか。
另外,在实现异步处理时,建议查看位于\HH\Asio下的集合处理和函数。
– \HH\Asio\m
– 支持异步的扩展(mysql, memcache, curl, stream)