ElixirとRailsのベンチマーク比較をした話
業務でAPIサーバーを作る事になり、何で実装しようか検討したという話です。
候補としてRails(定番)が上がっていたものの、
という事で他の選択を検討しました。
選択しとして
があがったので、RailsとElixirでAPIサーバーのプロトタイプを作ってベンチマーク比較をしてみました。
※ ElixirはErlangと同水準のBeamを吐くのでErlangは除外しています(ベンチを実際に計った結果、同程度の性能でした、こちらは別途結果を公開しようと思います)
またGo/Scalaについては僕自身そこまで熟知しているわけではないので今回は対象から外しています。
以下、プロトタイプのAPIサーバーの仕様です
- pingリクエストでpongを返す
- http://bench-server/ping -> pong
- mysqlからデータをJSONで取得、ただし複雑なクエリは投げない
- http://bench-server/users -> {user's json list}
https://github.com/ohr486/server_bench
使用したサーバーはAWS/EC2の、t2microインスタンス、OSは64bit CentOS7です。
以上の環境でabを使い、以下の様に計測しました。
- Rails: Rails4.2 + Ruby2.2 + nginx1.6.2 + unicorn4.8.2
- Elixir: Erlang17.4 + Elixir1.0.2 + Cowboy2.0
- DBアクセスをしないpingに対してリクエストをかける
- 各同時接続数毎に5回測定を行い、その平均を結果とする
- ab -n <同時接続数> -c <同時接続数>
- ab -n <同時接続数> -c <同時接続数>
- 同時接続を投げてエラーにならない最大同時接続数
- ElixirとRailsの最大接同時続数で接続数xNのアクセスを投げた場合の
- Request/Sec
- Time/Req
結果は以下となります。
https://docs.google.com/spreadsheets/d/1J8Rk9EwImbRifUPkqYdJuH9qzx8-szuLmNootQO6Z6U/edit#gid=0
(Failedが出ないギリギリの)最大同時接続数は
Rails: 130 / Elixir: 4900
最大同時接続時のRequest/Secは
Rails: 689 / Elixir: 4175
最大同時接続時のTime/Req(1リクエストあたり)は
Rails: 1.47msec / Elixir: 0.37msec
でした。
結論として、(webだけの性能を見れば)Elixirの方が良い結果が出ました。
もちろんRailsにもチューニングの余地がかなりあり、まだまだベンチ結果を上げる事は可能と思います。
ただどう頑張っても(僕のスキルでは)Elixirでの結果並みにRailsをチューニングで性能改善ができるイメージはわきませんでした。
(またRailsではなくSinatra等の軽量F/Wを使えばもっと良いベンチマーク結果がでると思います)
また今回のベンチマークではDBアクセスがありません(単純なping)が、DBアクセスのあるAPIのベンチマークを取れば、ElixirはDBがボトルネックになりここまでの性能は出ないと思います。(事実DBがボトルネックで他のAPIでは性能劣化しました)
以上をふまえて、僕の携わってるプロジェクトにてElixirの採用を決定しました。
おわり。
(注意)
このエントリは、Railsオセーという事を主張するものではありません。
APIサーバーにビジネスロジックをごりごり組み込むのであれば、Elixir/CowboyよりRailsを採用していたと思います。
事実、管理システムサイドはRailsを採用しております、要は適材適所という話で、たまたまElixir/Cowboyという選択肢があったので採用したのです。はい。