ベンチマークの発端
ある日,MatzさんがRTをしていたツイートの内容が気になりました.
Flaskはとにかく大量にフック、拡張できるポイントを用意してるからその抽象化の呼び出しツリーの部分だけ遅くなるし、1プロセスに複数アプリが並存することも考えているし、HTTPリクエスト以外で使うときのためにリクエストコンテキストとアプリコンテキストをわざわざ別に用意してたり、重すぎる。
— INADA Naoki (@methane) 2018年10月20日
あまり個人的な用途でPythonに速度を求めることはないので,そうなのかーぐらいに思っていました.
しかし,この後のツイートで言及されているFalconというWebフレームワークが気になり,調べてみると,公式のベンチマーク結果がありました.
どうやらFalconは凄く速いようです.
一方で,もう1つ気になったことがあり,それはGunicornのサイトにありました.GunicornはPythonでアプリケーションサーバーを構築する際によく使われるソフトですが,Gunicornを組み込みサーバーとして利用するためのドキュメントが公開されていました.
以前から,純Pythonの組み込みサーバーには興味があり,
PythonでもシングルバイナリでProductionReadyなhttpサーバーが欲しいっ!!
というドキュメントを書いていたりしました.そのため,Gunicornの性能についても気になっていました.
この辺の興味から,
Python組み込みサーバーとして速いサーバーは何か?
FlaskとFalconはどれだけ差があるのか?
ということが知りたくなったので,ベンチマークをすることにしてみました.
組み込みWebサーバー
今回,利用したPythonの組み込みWebサーバーはこれらです.
Gunicornは前節で書いた通り,よく使われるwsgiサーバーです.Tornadoは以前の記事でも紹介したWebフレームワークで,その一機能として提供されているwsgiサーバーを使います.割と知られていないところだとTwistedでしょうか.割と古くからあり,Bittorrentのコードにも使われているネットワーク系のライブラリで,最近ではPython実装のhttp2サーバーもあったりします.最後のwsgirefですが,これはライブラリ名ではなく,モジュール名です.Pythonの標準ライブラリに入っているリファレンス実装のwsgiサーバーを指しています.
Webフレームワーク
Flaskは一時期話題になったマイクロフレームワークですね.Falconはそれ以降に出てきたマイクロフレームワークです.あまり,情報は多いほうではないですが,速い.という噂だけはちょこちょこと聞くライブラリだったりします.
Flaskのコード
from flask import Flask
app = Flask(__name__)
@app.route("/")
def index():
return "Hello F1!"
Falconのコード
import falcon
class SampleApp:
def on_get(self, req, resp):
resp.body = "Hello F2!"
resp.status = falcon.HTTP_200
app = falcon.API()
app.add_route('/', SampleApp())
どちらもすごく小さく作ることができます.
ベンチマークツール
今までは簡単なベンチはapache benchを使っていたのですが,今回はこのvegetaを使います.golang製で割と使いやすいらしいです.今回は550rpsで180秒の間,負荷をかけます.
$ vegeta attack -duration=180s -rate 550
ベンチマーク結果
サーバー | フレームワーク | 成功率[%] | mean[ms] | 50%[ms] | 95%[ms] | 99%[ms] | max[ms] |
---|---|---|---|---|---|---|---|
gunicorn | falcon | 100.00 | 1.37 | 0.91 | 2.15 | 12.12 | 81.44 |
tornado | falcon | 100.00 | 1.13 | 0.81 | 1.65 | 8.66 | 52.87 |
twisted | falcon | 100.00 | 2.31 | 1.20 | 4.58 | 28.37 | 136.24 |
wsgiref | falcon | 81.42 | 790.66 | 2.92 | 3677.59 | 16476.12 | 44156.88 |
gunicorn | flask | 100.00 | 1.55 | 1.16 | 3.55 | 7.59 | 37.95 |
tornado | flask | 100.00 | 2.96 | 1.04 | 6.19 | 38.97 | 568.63 |
twisted | flask | 100.00 | 1633.42 | 1.99 | 10066.98 | 11590.31 | 11918.90 |
wsgiref | flask | 72.75 | 815.74 | 2.44 | 4739.70 | 16115.85 | 44172.28 |
#考察
今回やってみたところ,gunicornが安定の速さ.というところでしょうか.次点でtornadoという感じでしょうか.やはり,標準モジュールのwsgirefはあまり速くない.ライブラリの比較,という意味ではやはりfalconのほうが速い.という感じですね.ただTwistのようにすごく差が出る場合と,wsgirefのように出ない場合があり,その原因はよくわからないです.もしかしたら,Twisted+Flaskの場合は,Flaskの処理が遅いせいで,サーバー全体でのレスポンスが下がっている可能性があります.
では,Gunicorn+Falconが良いのか?というとそういうわけではなさそうです.
Gunicornはnginx等でリバースプロキシをするのが推奨されていますし,Falconは割と知見が少なかったりします.
#感想
色々なPythonの組み込みサーバーをまじめに調べてみましたが,意外に種類はあるものですね.しかし,本当に本番環境で稼働させると,セキュリティの知見なりが必要となったり,本番用の設定をきちんと考えるとすると,ノウハウが無かったりと困難も多いと思います.ただハッカソン等でサクッと作るのであれば十分使えると思うので,今後もちょこちょこと使っていきたいと思います.