前回の記事でDjangoとFlaskとPyramidを比較して、Flaskいいなーとなったので早速試してみました。
FlaskというPython Webフレームワークにて大規模向けと言われているBlueprintチュートリアルに沿って構築した機能をベンチマークして比較しています。Blueprintとは複数の小さなアプリ毎(機能毎)にViewを切り分けるFlaskの機能です。
構築後Apache Benchを利用して、PyPy3 2.4とPython3.5を比較した ベンチマーク を取得しています。
ディレクトリ構成
デフォルトの単一Viewと異なりviewsディレクトリを設置して、その中に機能毎のviewを設置していきます。今回はroot
とreport
機能を追加してみました。
テンプレートの抽象化
HTMLのHEADやBODYタグといった共通部分をmaster.html
切り分けて分離します。
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset="utf-8" />
<title>{% block title %}{% endblock %} - Hello Flask!</title>
<link type="text/css" rel="stylesheet"
href="{{ url_for('static',
filename='hello.css')}}" />
</head>
<body>
{% block body %}{% endblock %}
</body>
</html>
{% extends "master.html" %}
{% block title %}index{% endblock %}
{% block body %}
<h1>this is index page</h1><br />
<h3>report</h3>
<a href="{{ url_for('report.index') }}">report - index</a><br />
<a href="{{ url_for('report.report_list') }}">report - list</a><br />
{% endblock %}
URLの抽象化とトップページの定義
Flaskサーバはpython main.py
コマンドで起動します。main.py に機能毎のURLを紐付けます。
# -*- coding: utf-8 -*-
from flask import Flask
from views import root, report
app = Flask(__name__)
# 機能毎のURLを定義
app.register_blueprint(root.app, url_prefix="/")
app.register_blueprint(report.app, url_prefix="/report")
if __name__ == '__main__':
app.run(debug=True)
root機能の定義
サイトトップページを定義します。
# -*- coding: utf-8 -*-
from flask import render_template, Blueprint
# 第一引数の名称が、テンプレのurl_for内で呼び出すときの名称と紐づく
app = Blueprint("index",
__name__,
url_prefix='/<user_url_slug>')
# テンプレート内で呼び出すときは url_for('index.index')
@app.route("/")
def index():
return render_template('root/index.html')
report機能の定義
# -*- coding: utf-8 -*-
from flask import Module, render_template, Blueprint
app = Blueprint('report',
__name__,
url_prefix='/<user_url_slug>')
# テンプレート内で呼び出すときは url_for('report.index')
@app.route('/', methods=['GET'], strict_slashes=False)
def index():
return 'report index'
# テンプレート内で呼び出すときは url_for('report.report_list')
@app.route('/report_list', methods=['GET'], strict_slashes=False)
def report_list():
return 'report - list'
PyPy3 2.4とPython3.5でベンチマーク
debug=Falseと設定して、Apache Benchコマンドで並列度100で10,000回requestしてみました。Python3.5の方が26%高速に動作しました。サーバ起動はpython main.py
コマンドで行ったのでシングルプロセスでのベンチマークです。予想ではPyPyが圧倒的速度でぶっちぎると思っていたのですが蓋を開けてみたらPython3.5の方が早いという不思議な結果に終わりました。flaskはFlask==0.10.1
です。次はDBアクセス有りで調査してみたいと思います。
>>>ab -n 10000 -c 100 http://localhost:5000/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking localhost (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
Completed 10000 requests
Finished 10000 requests
Server Software: Werkzeug/0.11.2
Server Hostname: localhost
Server Port: 5000
Document Path: /
Document Length: 398 bytes
Concurrency Level: 100
Time taken for tests: 20.783 seconds
Complete requests: 10000
Failed requests: 0
Write errors: 0
Total transferred: 5530000 bytes
HTML transferred: 3980000 bytes
Requests per second: 481.16 [#/sec] (mean)
Time per request: 207.829 [ms] (mean)
Time per request: 2.078 [ms] (mean, across all concurrent requests)
Transfer rate: 259.85 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 2.6 1 74
Processing: 3 205 53.6 199 762
Waiting: 3 205 53.1 199 760
Total: 24 206 53.0 199 763
Percentage of the requests served within a certain time (ms)
50% 199
66% 204
75% 211
80% 214
90% 225
95% 236
98% 295
99% 571
100% 763 (longest request)
++++++++++++++++++++++++++
>>> python --version
Python 3.2.5 (b2091e973da6, Oct 19 2014, 18:30:58)
[PyPy 2.4.0 with GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.51)]
>>>ab -n 10000 -c 100 http://localhost:5000/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking localhost (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
Completed 10000 requests
Finished 10000 requests
Server Software: Werkzeug/0.11.2
Server Hostname: localhost
Server Port: 5000
Document Path: /
Document Length: 398 bytes
Concurrency Level: 100
Time taken for tests: 16.380 seconds
Complete requests: 10000
Failed requests: 0
Write errors: 0
Total transferred: 5530000 bytes
HTML transferred: 3980000 bytes
Requests per second: 610.52 [#/sec] (mean)
Time per request: 163.795 [ms] (mean)
Time per request: 1.638 [ms] (mean, across all concurrent requests)
Transfer rate: 329.70 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 5.8 0 195
Processing: 3 161 44.7 148 475
Waiting: 3 161 44.5 148 475
Total: 59 162 43.9 148 476
Percentage of the requests served within a certain time (ms)
50% 148
66% 151
75% 154
80% 156
90% 239
95% 276
98% 299
99% 322
100% 476 (longest request)
++++++++++++++++++++++++++4
>>> python --version
Python 3.5.0
並列度1なら平均応答速度1.8 - 2.5msで応答しました。いまのところFlaskすごく早い( ・ㅂ・)و