Es ist die Saison von ISUCON. ISUCON verwendet normalerweise das typische Mikroframework in jeder Sprache, aber Python verwendet Flask vorerst.
Flask sieht beim Schreiben einer einfachen Beispiel-App sicherlich wie ein Mikroframework aus. Strukturell gibt es jedoch viele Haken und Signale, und es ist ein schweres Design.
Der kombinierte Kolbenkörper und das Werkzeug haben eine Größe von Zehntausenden von Linien. Selbst eine reine Hello World-App hat Dutzende von Funktionsaufrufen hinter den Kulissen.
Wie Flask ist Bottle ein Framework mit mehreren Threads, einem Kontextstapel, der Thread-Locals verwendet, und Erweiterungen, aber seine Struktur ist viel einfacher als die von Flask. Der Quellcode besteht aus 3000 Zeilen pro Datei, und der Overhead des Frameworks beträgt etwa die Hälfte des Overheads von Flask.
Ich habe eine kleine Messung mit der Hello App gemacht. Vergleichen Sie auf dem MacBook Air 2013 Mid (Core i5 1,3 GHz) eine Single-Thread-Hello-App mit einem Prozess und wrk -t1 -c1. Python ist CPython 3.4.1 und der Webserver ist Meinheld (Github neueste Version).
wsgi:
$ wrk -t1 -c1 http://localhost:6000/
Running 10s test @ http://localhost:6000/
1 threads and 1 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 118.89us 46.59us 0.99ms 91.40%
Req/Sec 7.57k 622.67 9.90k 67.44%
71708 requests in 10.00s, 11.08MB read
Requests/sec: 7170.95
Transfer/sec: 1.11MB
Bottle:
$ wrk -t1 -c1 http://localhost:6000/
Running 10s test @ http://localhost:6000/
1 threads and 1 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 221.92us 678.78us 18.72ms 99.81%
Req/Sec 4.86k 418.08 6.44k 78.08%
46110 requests in 10.00s, 7.74MB read
Requests/sec: 4611.09
Transfer/sec: 792.53KB
Flask:
$ wrk -t1 -c1 http://localhost:6000/
Running 10s test @ http://localhost:6000/
1 threads and 1 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 476.59us 134.74us 1.71ms 79.35%
Req/Sec 2.11k 194.96 3.10k 65.86%
19967 requests in 10.00s, 3.35MB read
Requests/sec: 1996.71
Transfer/sec: 343.18KB
Betrachtet man den Unterschied in der durchschnittlichen Latenz, so sind etwa 100 μs für die Flasche und etwa 350 μs für die Flasche Overheads für Roh-WSGI, was mehr als dem Doppelten der Gesamtleistung entspricht.
Bottle unterstützt auch Jinja-Vorlagen. Selbst wenn Ihre ursprüngliche App Flask war, sollten Sie relativ einfach zu Bottle wechseln können. In Fällen, in denen es viele Pfade gibt, die nur den HTML-Teil zwischenspeichern und die Daten aus Memcached wieder zusammenfügen, sollte die Leistung dieses Basisteils ein nicht zu vernachlässigender Unterschied sein.
Zuletzt werde ich den gemessenen Quellcode einfügen. Versuch es bitte.
import flask
import bottle
app = flask.Flask(__name__)
bottle_app = bottle.app()
@bottle_app.route('/')
@app.route('/')
def index():
return b"Hello, World"
def wsgi(env, start):
c = b"Hello, World"
start("200 OK", [('Content-Type', 'text/plain'), ('Content-Length', str(len(c)))])
return [c]
#Startmethode
# Flask: gunicorn -k meinheld.gmeinheld.MeinheldWorker -b :6000 app:app
# Bottle: gunicorn -k meinheld.gmeinheld.MeinheldWorker -b :6000 app:bottle_app
# wsgi: gunicorn -k meinheld.gmeinheld.MeinheldWorker -b :6000 app:wsgi
Recommended Posts