PHP の Guzzle で直列 vs 並列

前やった node.js の Promise で直列 vs 並列を php でやってみた。 素の php だと非同期処理はめんどくさいので 今回は Guzzle を使ってみた。

Guzzle は非同期もできる http クライアントだけど、 Guzzle Promises を使えば 一般的な処理も非同期で書けるみたい。

<?php
/*
 * PHP の Guzzle で直列 vs 並列
 */

require './vendor/autoload.php';

function createUrl(int $sec) {
    return 'http://httpbin.org/delay/' . $sec;
}

function serial(array $urls) {
    $client = new \GuzzleHttp\Client();

    $bodies = [];
    foreach ($urls as $url) {
        $response = $client->request('GET', $url);
        $bodies[] = $response->getBody()->getContents();
    }
    return $bodies;
}

function parallel(array $urls) {
    $client = new \GuzzleHttp\Client();

    $promises = [];
    foreach ($urls as $url) {
        $promises[] = $client->requestAsync('GET', $url);
    }
    $responses = \GuzzleHttp\Promise\all($promises)->wait();

    $bodies = [];
    foreach ($responses as $response) {
        $bodies[] = $response->getBody()->getContents();
    }
    return $bodies;
}

function main() {
    $urls = [];
    foreach (range(1, 4) as $sec) {
        $urls[] = createUrl($sec);
    }

    $startTime = new \DateTime();
    serial($urls);
    $diff = $startTime->diff(new \DateTime());
    var_dump('serial: '. $diff->format("%s sec"));

    $startTime = new \DateTime();
    parallel($urls);
    $diff = $startTime->diff(new \DateTime());
    var_dump('parallel: '. $diff->format("%s sec"));
}
main();

動かしてみる。

$ composer require guzzlehttp/guzzle
$ php main.php
/path/to/main.php:50:
string(14) "serial: 11 sec"
/path/to/main.php:55:
string(15) "parallel: 4 sec"

ちゃんと並列で動いてるみたい。

php 7.2.4 で確認