こんにちは。エンジニアの尾澤です。
先日、酒井がLaravel5.0:FormRequestを使ったValidationというエントリでLaravelのTipsをご紹介しましたが、今回は、そのLaravelと同じコミュニティで開発している別の軽量フレームワークであるLumenとパフォーマンスの比較をしてみたいと思います。バージョンは5.1を使用します。
Lumenのベンチマークとしては、公式サイトで他の軽量フレームワークであるSilexとSlim 3との比較が紹介されていますが、相互にコードの移植性が高いLaravelとの比較がなかったので、調べてみました。
LaravelとLumenの機能面での比較はこちらのエントリーによくまとめられていますので、参考にしてください。
検証環境
検証には、同じくLaravelコミュニティが提供しているVagrant環境であるHomesteadを使用しました。なお、HomesteadはHHVMをサポートしていますが、今回は使用していません。
検証マシンのスペックは以下の通りです。ちなみにメドピアでは、エンジニア・デザイナの全員にMacbook Proを支給していますので、開発作業は快適です(ง ˙ω˙)ว☆
MacBook Pro (Retina, 14-inch, Mid 2014) Processor 2.8GHz Intel Core i5 Memory 16GB 1600MHz DDR3 Storage 500GB Flash Storage
検証環境には、それぞれのフレームワークで同じ仕様のアプリケーションを実装しました。アプリケーションはシンプルに、GETリクエストに対して常に同じ内容のテキストをレスポンスとして返します。テキストはJSONフォーマットで、Homestead内のMySQLから取得したデータを使用します。LaravelとLumenでは多少書き方は変わるところもありますが、クラス構成やロジックは同じです。フレームワークの以下の機能を利用しました。
- Routing
- Controllers
- Service Providers
- Eloquent ORM
速度の比較
速度の比較にはApache Benchを使用しました。接続数100で1000リクエストを発行して、1リクエストあたりのレスポンスタイムを比較してみます。
まずはLaravelから。
user:homestead mymac$ ab -n 1000 -c 100 http://laravel.app/sample 〜中略〜 Concurrency Level: 100 Time taken for tests: 113.675 seconds Complete requests: 1000 Failed requests: 0 Total transferred: 12632114 bytes HTML transferred: 11679000 bytes Requests per second: 8.80 [#/sec] (mean) Time per request: 11367.500 [ms] (mean) Time per request: 113.675 [ms] (mean, across all concurrent requests) Transfer rate: 108.52 [Kbytes/sec] received 〜後略〜
Time per requestを確認すると、1リクエストあたり113.675 msかかってることが分かります。
Laravelの検証にあたっては
php artisan optimize
コマンドによるコード最適化を行っていません。最適化による速度の改善については別の機会に書きたいと思います。
次にLumen。
user:homestead mymac$ ab -n 1000 -c 100 http://lumen.app/sample 〜中略〜 Concurrency Level: 100 Time taken for tests: 30.072 seconds Complete requests: 1000 Failed requests: 0 Total transferred: 11840000 bytes HTML transferred: 11679000 bytes Requests per second: 33.25 [#/sec] (mean) Time per request: 3007.196 [ms] (mean) Time per request: 30.072 [ms] (mean, across all concurrent requests) Transfer rate: 384.49 [Kbytes/sec] received 〜後略〜
Lumenでは、1リクエストあたり30.072 msでした。Laravelの113.675 msと比較すると3.78倍も速いという結果になりました!こんなに差が出ると思わなかったのでビックリ。
負荷の比較
それでは、サーバの負荷についてはどうでしょう?いくら速くてもリソース消費が著しければ意味がないですからね。Apache Benchを実行している状態で、vagrantインスタンスの負荷をvmstatコマンドで記録し、gnuplotでグラフ化してみました。
Laravelの負荷
Lumenの負荷
CPU負荷のグラフを比較すると、Lumenの負荷の方が軽いことが分かります。vmstatの実測値からアイドリング率を平均すると、Laravelが9.0%、Lumenが31.4%でしたので、LumenのCPU負荷はLaravelの75.4%ということになります。だいぶCPUに優しいですね!
メモリ負荷については若干Lumenの方が少ないように見えますが、空きメモリ量の実測値を平均すると、Laravelが879MB、Lumenが897MBで、ほとんど変わらないですね。誤差の範囲といってもよさそうです。フレームワーク自体の消費メモリに優劣ありませんでした。
サイズの比較
Laravelのサイズ
vagrant@homestead:~$ du -sk laravel/vendor/laravel/framework/ 3416 laravel/vendor/laravel/framework/
Lumenのサイズ
vagrant@homestead:~$ du -sk lumen/vendor/lumen/vendor/illuminate/ lumen/vendor/laravel/lumen-framework/ 2588 illuminate 292 laravel/lumen-framework/
フレームワークそのもののサイズはどうでしょう?composerで取得したコアライブラリの容量を比較してみたところ、Laravelが3416 KB、Lumenが292 KB 2880KBで、LumenのサイズはLaravelの8.5% 84.3%という結果になりました。かなり減量されていますね!自分も、せめて80%くらいにまでダイエットしたいところです…。 軽量というには減量具合が中途半端ですね。自分の場合、それくらいダイエットできればBMI値が人並みになるんですが…。
Lumenのサイズに依存パッケージの分が含まれていないというご指摘をいただきました。illuminateパッケージのサイズを加味して計算して修正しました。
まとめ
以上の検証結果をまとめると、以下のような結論になりました。
- LumenはLaravelの約4倍速い
- LumenはLaravelの約75%CPUに優しい
- LumenはLaravelと同じくらいメモリを消費する
- LumenはLaravelの
約10%約85%の大きさ
Lumenは拡張性や機能に制限がありますが、その範囲で要求を満たせるものであれば、フルスタックのLaravelではなくLumenを使ってみるという選択肢もありかもしれませんね。
今回使用したソースコードは、https://github.com/medpeer-inc/benchmark-laravel-lumenに置いてありますので、ぜひ参考にしてみてください。