Phoenix Framework(以下、Phoenix)は、Elixir のための Web アプリケーションフレームワークです。
Phoenix の開発者 José Valim 氏は Ruby on Rails のコミッタだったため(Rails Contributors - #5 José Valim を見る限り、2014年まで?)、使い勝手はとても Rails に似ています。そのため、Phoenix は Rails とよく比較され、「Rails よりも10倍近く速い」という評判を時々目にします。
ただ、その評判の出処になったベンチマークについて、僕は具体的な内容を知りませんでした。また、記事によってベンチマークのリンク先がまちまちで、それぞれの関係がよくわかりませんでした。自分で Phoenix を使ってみるにあたり、このあたりを少し調べてみたので、その結果をメモしておきます。
最初のベンチマーク
Phoenix と Rails に関する最初のベンチマークは、Chris McCord(Programming Phoenix: Productive, Reliable, Fast の著者)による2014年7月のブログ記事のようです。
この記事は「Phoenix は Rails より10.63倍速い」というベンチマーク結果を示しています。ちなみに、これは Elixir vs Ruby Showdown というシリーズの2番目のポストで、最初のポスト(Elixir vs Ruby Showdown - Part One)では「Ruby の i18n gem と比較して Elixir 版は73倍速い」という結果を出してます。
このベンチマークの内容は以下のようなものです。この特徴は、後述する他のベンチマークにも引き継がれています。
- URL ‘/:title’ の :title 部分をコントローラに渡す
- コントローラは、モデルの返り値を想定したマップ(固定値)の配列をビューに渡す
- ビューは、受け取った配列を回して HTML を生成し、クライアントに返す
- データベースへのアクセスは行わない
- ログ出力は行わない
- ENV = production で動作させる
- ベンチマークツールには wrk を使って、30秒間テストする
具体的なコードの説明も載っているので、後述するベンチマークを読むにしても、まずこのブログ記事は読んでおいた方が良いです。
ベンチマーク対象の拡大
その後、このベンチマークに触発されて、ベンチマーク対象を他のフレームワークに広げたものが Matthew Rosenberg 氏により公開されました。
Phoenix は、Rails よりむしろ Sinatra に似た軽量フレームワークではないか、との理由から、比較対象は主に Sinatra にインスパイヤされたフレームワークから選ばれています。また、Phoenix の実装の基盤である Plug というライブラリを素で使った場合も追加されています。
- Phoenix (Elixir)
- Plug (Elixir)
- Rails (Ruby)
- Sinatra (Ruby)
- Express, Express Cluster (JavaScript)
- Martini (Go)
- Gin (Go)
- Play Framework (Java)
このテストは、Phoenix のバージョンアップに合わせて、何度か実施されています。
- 2014年7月: Comparative Benchmark Numbers, Round 1
- Elixir 1.0.2
- 2015年1月:Comparative Benchmark Numbers, Round 2
- Elixir 1.0.2, Erlang/OTP 17.4
- 2016年7月:Comparative Benchmark Numbers, Round 3
- Elixir 1.3.2, Erlang/OTP 19.0.2
Round 1 と 2-3 はスペックが違うので単純に比較できません。
- Round 1: 3.4GHZ Core i7 (quad core), 12GB RAM
- Round 2-3: 4.0GHZ Core i7 (quad core), 32GB RAM
Round 1 はスペックが低いので、単純比較できるのは Round 2 と 3 のみです。Phoenix の結果だけ比較すると、Round 3 は 2 よりも若干遅くなっています。Plug の結果はほとんど変わっていないので、Phoenix に機能が増えたからでしょうか?
Round 3 の結果を見ると、Phoenix は Play より Consistency は優れているものの、Throughput は Play の約 0.47 倍となっています。Elixir は stop-the-world GC がないので Java より高速、と思っていたので、最初にこの結果を見たときはかなりがっかりしました。
高スペックなベアメタルサーバ上での結果
2015年7月に、上記の phoenix-showdown を Rackspace のベアメタルサーバ(CPU Dual 2.8 Ghz, 10 core, RAM 128 GB)で実行した結果が公開されました。
Comparative Benchmark Numbers @ Rackspace
スペックが高いほど Elixir の真価が発揮されるのか、このベンチマークでは、Phoenix の throughput は Play とほぼ同じか若干上で、Consistency では引き続き上回っています。Rails との差は更に開いて、Phoenix の throughput は Rails の15倍になっています。
感想(と職場ブログの宣伝)
素の状態では、Phoenix は Rails よりも10倍以上高速なのは確かなようです。ただ、他のコンパイル言語(Java や Go)と比較すると、throughput については決定的な差は無さそうです。
また、これらのベンチマークはデータベースアクセスやログ出力といった、普通のアプリには絶対にある機能を省いているので、周辺ライブラリの充実度によっては、開発者の多い Java & Play Framework で実装した方が、総合的には速くなるのかもしれません。Rails 開発者が多い環境なら Phoenix に飛びついてもよさそうですが、Java 開発者が多い環境では Play のほうが速い、ということもあるのかもしれません。
そのあたりが気になって、Elixir (その2)とPhoenix Advent Calendar 2016 の24日目として、Phoenix で書いた簡単なアプリケーションサーバに、HBase アクセスや、ファイルへのログ出力を足したら、性能はどう変わるか、という話を書きました。時間の都合で Play との比較まではできていませんが、今後気が向いたらそこまで試してみたいと思っています。