Help us understand the problem. What is going on with this article?

Swooleによる非同期リクエストとGuzzleによる非同期リクエストのベンチマーク

More than 1 year has passed since last update.

Swoole との出会い

PHPカンファレンス福岡の前夜祭、及び afterhack にて、@uzulla さんが、
最近メールフォームかいてないメールフォーマーによる、ちょっとだけ変わった一応PHPのメールフォーム(?)のお話
という発表をされていました。
その中で、PHPのSwooleエクステンションのことについてお話されていました。

その話を聞いて興味を持ったので、今回ベンチマークを取ってみることにしました。

Swoole とは? という説明は上記の発表資料に書いてあるので割愛させていただきます。
上記資料には、
- 主にリクエストを処理するphp-fpmの代用としてSwoole
- タイマー
- シングルトン
- coroutine による非同期リクエスト

など盛り沢山ですが、
今回の話は、 coroutine による非同期リクエストだけ使いたい場合の話、
つまり、PHPで書いてあるコードの一部だけ非同期でリクエストを投げたい時の話です。

自分がパッと思いつくのは、
資料にも書かれているようにDNSを引く場合とか、SESにリクエスト投げつける場合とかです。
今までだと、Guzzle で実装していました。

環境

Docker on Mac 上に、 centos:latestイメージから立ち上げたコンテナで実験を行いました。
Swoole を使うときは、Mac上で直接ではなく、仮想環境上で行ったほうが良いらしいです。
Mac上よりもLinux上の方が処理が10倍速いとも、100倍速いとも。。。

ということで、

docker pull centos:latest
docker run --rm -it centos:latest /bin/bash
yum update -y && yum groupinstall "Development Tools" -y && yum install git wget curl vim -y
# https://webbibouroku.com/Blog/Article/centos-php7
yum install epel-release -y && rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
yum install --enablerepo=remi,remi-php72 php php-swoole -y

を行えば環境構築は完了です。
あとは、

curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer
composer require guzzlehttp/guzzle

を行うと、guzzle も使えるようになります。

実装

Guzzle を使った場合、Swoole を使った場合、普通に file_get_contentsを使った場合の3種類のコードを書いていきます。

Guzzle

参考にした記事

<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;

$client = new Client();
$promises = [];
for ($i = 0; $i < 10; $i++) {
    $promises[] = $client->requestAsync('GET', 'https://hogehogehogehoge.hoge/');
}
$responses = \GuzzleHttp\Promise\all($promises)->wait();

Swoole

<?php
for ($i=0; $i<10; $i++) {
  go(function() {
    $http = new \Swoole\Coroutine\Http\Client('hogehogehogehoge.hoge', 80);
    $ret = $http->get('/');
  });
}

file_get_contents

<?php
for($i=0; $i<10; $i++) {
  file_get_contents('https://hogehogehogehoge.hoge/');
}

と、3種類のコードを書きました。

ベンチマーク結果

ベンチマークは、

time php hoge.php

を5回ずつ実行し、実行速度の平均値をベンチマーク結果としています。

結果は、

Guzzle Swoole file_get_contents (参考) Guzzle 直列
real 0m0.597s 0m0.114s 0m3.410s 0m0.906s
user 0m0.112s 0m0.024s 0m0.154s 0m0.064s
sys 0m0.102s 0m0.006s 0m0.024s 0m0.066s

となりました。
今回の結果だけでいくと、 Swoole が Guzzle の5倍ほど早いことになります。
また、Guzzle のコードは、Promise\all()->wait();
など、独特のコードを書く必要がありますが、
Swoole のコードは、割と直感的に書くことができます。

ということで、Swoole の有効性の片鱗が見えてきたので、
次は、CPU使用量やメモリ使用量などについても調べてみようと思います。

(今回は、サーバー立てるのめんどくさかった。)

もし問題なかったら、実戦投入も視野に入れていこうと思います。

余談

今回使ったSwooleのバージョンは、Swoole4 です。
Swoole の新機能に関しては、カジュアルに壊れてるらしい(@uzulla さん談)ので、
最新版のSwoole を使うときには注意が必要だそうです。

使ってみた感想

速い!
しかも、直感的に書けるので、割と重宝しそうです。
通常、APIのリクエスト数には上限があったりするので、
そのへんをどのように書けるかは少し調査が必要です。

あと、今回のメインテーマではないのですが、

Guzzle 直列と file_get_contents の間の実行時間の差が気になります。

機会があったら調べてみたいです。 (CPU使用量とかのほうが先。)

fusic
個性をかき集めて、驚きの角度から世の中をアップデートしつづける。
https://fusic.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away