PHP8.1からは Fibers を使って非同期処理を記述することができますが
PHP 7でも amphp/amp を使う事でとても簡単に非同期処理を記述・実行することができます。
composer require amphp/amp
composer require amphp/parallel-functions
例として3つのWEBサイトへ非同期でアクセスして、取得したhtmlのバイト数を返すプログラムを書いてみます
test.php
<?php
require_once './vendor/autoload.php';
use function Amp\ParallelFunctions\parallelMap;
use function Amp\Promise\wait;
function testFunc()
{
$responses = wait(parallelMap([
'https://stackoverflow.com/',
'https://google.com/',
'https://github.com/',
], function ($url) {
$options = stream_context_create(array('ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false
)));
return file_get_contents($url, false, $options);
}));
echo strlen($responses[0]) . "\n";
echo strlen($responses[1]) . "\n";
echo strlen($responses[2]) . "\n";
}
function format_microtime ( $time, $format = null )
{
if (is_string($format)) {
$sec = (int)$time;
$msec = (int)(($time - $sec) * 100000);
$formated = date($format, $sec). '.'. $msec;
} else {
$formated = sprintf('%0.5f', $time);
}
return $formated;
}
$start_time = microtime(true);
// 処理の実行
testFunc();
$end_time = microtime(true);
$processing_time = $end_time - $start_time;
echo "処理時間:".format_microtime($processing_time)."秒\n";
<?php
require_once './vendor/autoload.php';
function testFunc()
{
$options = stream_context_create(array('ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false
)));
$responses[] = file_get_contents('https://stackoverflow.com/', false, $options);
$responses[] = file_get_contents('https://google.com/', false, $options);
$responses[] = file_get_contents('https://github.com/', false, $options);
echo strlen($responses[0]) . "\n";
echo strlen($responses[1]) . "\n";
echo strlen($responses[2]) . "\n";
}
function format_microtime ( $time, $format = null )
{
if (is_string($format)) {
$sec = (int)$time;
$msec = (int)(($time - $sec) * 100000);
$formated = date($format, $sec). '.'. $msec;
} else {
$formated = sprintf('%0.5f', $time);
}
return $formated;
}
$start_time = microtime(true);
// 処理の実行
testFunc();
$end_time = microtime(true);
$processing_time = $end_time - $start_time;
echo "処理時間:".format_microtime($processing_time)."秒\n";
php test.php
結果例
180126
51223
279741
処理時間:1.07782秒
それぞれ10回ずつ実行した結果はこちらになります
ampを使った非同期実行 |
---|
処理時間:0.89127秒 |
処理時間:0.84902秒 |
処理時間:1.52270秒 |
処理時間:1.29796秒 |
処理時間:1.51700秒 |
処理時間:0.99289秒 |
処理時間:0.97136秒 |
処理時間:0.83685秒 |
処理時間:0.86408秒 |
処理時間:1.06043秒 |
平均は 1.08 sec
(0.89127+0.84902+1.52270+1.29796+1.51700+0.99289+0.97136+0.83685+0.86408+1.06043)/10
非同期を使わず実行 |
---|
処理時間:1.62977秒 |
処理時間:1.55046秒 |
処理時間:1.56966秒 |
処理時間:1.76191秒 |
処理時間:1.55104秒 |
処理時間:1.69673秒 |
処理時間:1.74086秒 |
処理時間:1.57090秒 |
処理時間:1.69566秒 |
処理時間:1.65347秒 |
平均は : 1.64 sec (1.62977+1.55046+1.56966+1.76191+1.55104+1.69673+1.74086+1.57090+1.69566+1.65347)/10
(ウェブサーバーの設定権限によりけりだとは思いますが、WEBサーバから実行されたPHPの場合はうまく子プロセスが起動できずエラーとなります。)