kumama go言語とかgolangとかGAEとかネットサービスとかその他色々・・・

15Feb/110

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):
pass

class 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' % host

import 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使うことも無いなに変わるから不思議。ログ出すとパフォーマンスは悪くなりますがまぁ良いかと思えなくも無いのでとりあえず出す感じで。

ちなみにgevent/bottleだとこんな感じのコードに。

from gevent import wsgi
application = bottle.default_app()
wsgi.WSGIServer(('', 8088), application).serve_forever()

と、頑張ったところでSQLAlchemyがちょい重ということに気づいてorzなのですが…。

Comments (0) Trackbacks (0)

No comments yet.


Leave a comment

No trackbacks yet.