PHP Web Framework Benchmark 2019

ローカルの仮想環境で各PHPフレームワークのベンチマークを測定しました。以下はその測定結果をまとめたものです。なお、測定結果は測定する環境や条件によって異なると思います。フレームワーク選定の際は、ご自身の環境や条件で測定することをお勧めします。

##環境情報
- Ubuntu 18.04.2 LTS
- PHP/7.3.7（PHP-FPM with OPcache）
- Nginx/1.15.8


##前提条件

- "Hello World"を出力するだけのシンプルなコントローラクラスを使用する
- フレームワークに環境設定がある場合は本番環境設定にする（デバッグモードもOFF）
- オートローダーの最適化を行う [^1]
- フレームワークにルーティングや設定ファイルのキャッシュ機能がある場合はキャッシュを行う

##測定ツール

ツール：[wrk](https://github.com/wg/wrk)
実行条件：スレッド数10、コネクション数10（1スレッドあたり1コネクション）

```shell
# 実行例
wrk -t10 -c10 -d10s http://localhost/hello
```

##測定結果

| フレームワーク | GitHub<br>スター数 | バージョン | Requests/sec |Peak Memory [^2]|
|:--|--:|:--|--:|--:|
|[Laravel](https://laravel.com/)|53.8k|5.8.29|6.29|2.59M|
|[Laravel (Lumen)](https://lumen.laravel.com/)|1k|5.8.11|38.03|1.03M|
|[Symfony](https://symfony.com/)|21.3k|4.3.2|3.49|1.92M|
|[Zend Framework](https://framework.zend.com/)|5.7k|3.0.1|9.48|1.43M|
|[CakePHP](https://cakephp.org/jp)|7.9k|3.8.1|14.08|1.72M|
|[CodeIgniter](https://www.codeigniter.com/)|17.5k|3.1.10|54.10|0.70M|
|[Yii2](https://www.yiiframework.com/)|13k|2.0.23|26.85|1.47M|
|[FuelPHP](https://fuelphp.com/)|1.4k|1.8.2|26.35|0.93M|
|[Phalcon](https://phalconphp.com/ja/)|9.8k|3.4.4|199.97|0.67M|
|[ice framework](https://www.iceframework.org/)|0.3k|1.4.1|108.85|0.67M|
|[Slim](http://www.slimframework.com/)|10k|3.12.1|41.31|0.91M|
|[PHPixie](https://phpixie.com/)|-|3.13|6.49|1.19M|
|[StaticPHP](https://staticphp.gm.lv/)|-|1.1.0|52.08|0.71M|
|[Fat-Free Framework](https://fatfreeframework.com/)|2.3k|3.6.5|329.96|0.74M|
|[Siler (without Swoole)](https://siler.leocavalcante.dev/)|0.7k|1.5.3|81.64|0.67M|
|[Siler (with Swoole)](https://siler.leocavalcante.dev/swoole)|0.7k|1.5.3|1698.66|1.56M|

:bar_chart: Requests/sec
![tmp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184074/3cfa20b3-1e22-f7d5-78ef-b41a111238ee.png)

:bar_chart: Peak Memory
![tmp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184074/b34152a1-a34c-40cb-c48b-8d9b3e7b9250.png)

#テンプレートエンジンベンチマーク（2019/08/05追記）

##環境情報
同上

##前提条件

- "Hello xxxx"を出力するだけのシンプルなビューを使用する（xxxxには変数をアサイン）
- オートローダーの最適化を行う [^1]
- キャッシュ機能がある場合はキャッシュを行った状態で測定する

##測定ツール
同上

##測定結果

| エンジン | GitHub<br>スター数 | バージョン | Requests/sec |
|:--|--:|:--|--:|
|[Latte](https://latte.nette.org/)|0.4k|2.5.2|155.61|
|[Plates](http://platesphp.com/)|1k|3.3.0|149.92|
|[Smarty](https://www.smarty.net/)|1.5k|3.1.33|89.25|
|[Twig](https://twig.symfony.com/)|6.2k|2.11.3|89.02|
|[Blade(standalone ver.) [^3]](https://github.com/jenssegers/blade)|0.3k|1.2.2|43.26|

:bar_chart: Requests/sec
![tmp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184074/2d2102b3-9f4d-e70c-5ba3-c160026bf471.png)

#フレームワークベンチマーク（2019/10/30追記）

以下の言及がありましたのでOPCacheチューニング後に再計測しました。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Laravel は素だとゴミみたいに遅いけど OPCache とかでチューニング限界までやれば C エクステンションのフレームワークに体感では劣らないぐらいの速度出るよ</p>&mdash; mpyw🍺2年目Webエンジニア (@mpyw) <a href="https://twitter.com/mpyw/status/1189213565519060993?ref_src=twsrc%5Etfw">October 29, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">opcache.memory_consumption=128<br>opcache.interned_strings_buffer=8<br>opcache.max_accelerated_files=16229<br>opcache.validate_timestamps=0<br><br>これが本気の設定</p>&mdash; mpyw🍺2年目Webエンジニア (@mpyw) <a href="https://twitter.com/mpyw/status/1154650626921340928?ref_src=twsrc%5Etfw">July 26, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 


| フレームワーク | チューニング前<br>Requests/sec |チューニング後<br>Requests/sec|
|:--|--:|--:|
|[Laravel](https://laravel.com/)|6.29|41.03|
|[Laravel (Lumen)](https://lumen.laravel.com/)|38.03|284.97|
|[Symfony](https://symfony.com/)|3.49|98.53|
|[Zend Framework](https://framework.zend.com/)|9.48|218.05|
|[CakePHP](https://cakephp.org/jp)|14.08|125.01|
|[CodeIgniter](https://www.codeigniter.com/)|54.10|60.51|
|[Yii2](https://www.yiiframework.com/)|26.85|49.9|
|[FuelPHP](https://fuelphp.com/)|26.35|42.65|
|[Phalcon](https://phalconphp.com/ja/)|199.97|271.39|
|[ice framework](https://www.iceframework.org/)|108.85|109.97|
|[Slim](http://www.slimframework.com/)|41.31|404.37|
|[PHPixie](https://phpixie.com/)|6.49|105.15|
|[StaticPHP](https://staticphp.gm.lv/)|52.08|130.17|
|[Fat-Free Framework](https://fatfreeframework.com/)|329.96|340.32|
|[Siler (without Swoole)](https://siler.leocavalcante.dev/)|81.64|427.17|

:bar_chart: チューニング後 Requests/sec
![tmp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184074/e55024be-1ee6-e49f-9258-6b2963d1d4aa.png)



[^1]: https://getcomposer.org/doc/articles/autoloader-optimization.md
[^2]: レスポンス返却直前に[memory_get_peak_usage(false)](https://www.php.net/manual/ja/function.memory-get-peak-usage.php) で値を取得
[^3]: Laravelのライブラリに依存しているため遅いが、依存ライブラリのない[BladeOne](https://github.com/EFTEC/BladeOne)というのもあり、こちらの方がスループットは良い