Python simple_server tuning
GAE/PythonでごそごそやってますがたまーにGAEじゃ出来ない事をしたくなるときが有ります。ローカルのデバイス操作したりファイルごにょごにょしたり。そんな時は…Apache入れてmod_wsgi入れて…って言うのが王道にも思いますが結構大変。いっそのことdev_appserverで逃げようかとか思ったりもするもののライセンスも良く解からん上、シングルスレッド動作のwebサーバなので気が引けます。
で、Pythonに漏れなく付いてくるwsgiref.simple_serverとbottle+sqlalchemy/sqlite+flaskで落ち着いてたんですがやっぱりパフォーマンスが…。って事でちょっとぐぐる先生に聞いてみるとこんなページを紹介されるのでした。
Nicholas Piël » Benchmark of Python Web Servers
すげー、その調査力に感服。って違うry
gevent/libeventが良いですね~。wsgiref.simple_serverだと 2.6TPS エラー有りまくりだったアプリを試しにgevent.wsgi.WSGIServerにするとそれだけで13.7TPS!エラーも無しといい感じ。なんですが個人的なホーム鯖でgevent/libeventは流石にやり杉な雰囲気です。お試しはLinuxでやってますが諸事情からホーム鯖はWindowsです(ドライバがWindowsしかない…)。Internet公開もしないしってことでもうちょっとwsgiref.simple_serverで頑張ってみることにします。
そもそもシングルスレッドを何とかします。
from SocketServer import ThreadingMixIn
class ThreadingWsgiServer(ThreadingMixIn, WSGIServer):
passclass ThreadingWSGIRefServer(ServerAdapter):
def run(self, handler): # pragma: no cover
from wsgiref.simple_server import make_server, WSGIRequestHandler
if self.quiet:
class QuietHandler(WSGIRequestHandler):
def log_request(*args, **kw): pass
self.options['handler_class'] = QuietHandler
self.options['server_class'] = ThreadingWsgiServer
srv = make_server(self.host, self.port, handler, **self.options)
srv.serve_forever()bottle.run( server=ThreadingWSGIRefServer, host='0.0.0.0', port=8080,
interval=1, reloader=False, quiet=True )
ついでにログ抑制もやってみたり。後、Windowsだと特に遅くなるクライアントIPアドレスのDNSリバースlookupをhttp://bugs.python.org/issue6085を参考に外します。まー、ログ出さないなら外す必要も無いんですが、出す出さないでパフォーマンスの変化を見るために一応。
def _bare_address_string(self):
host, port = self.client_address[:2]
return '%s' % hostimport BaseHTTPServer
BaseHTTPServer.BaseHTTPRequestHandler.address_string = \
_bare_address_string
ぐぐる先生はこんなの↓も教えてくれましたがこれはちょっとやり杉。
def getfqdn(name=''):
return name
import socket
socket.getfqdn=getfqdn
quiet=Falseで8.4TPS、quiet=Trueで 10.9TPSって所まで改善。5倍差があると流石にgeventしかないなと思うものの2倍差も無いところまでくるとまーgevent使うことも無いなに変わるから不思議。ログ出すとパフォーマンスは悪くなりますがまぁ良いかと思えなくも無いのでとりあえず出す感じで。