gunicornメモ

unicornpython版だとか。
Gunicorn - Python WSGI HTTP Server for UNIX
ubuntuだとaptでbuild-essentialをいれとけば、easy_installやpipで問題なくインストールできるっぽい。
Workerは差し替えが可能らしい。id:mopemope先生のmeinheldには、gunicorn用のWorkerが含まれている。

$ cat myapp.py
def app(environ, start_response):
    data = "Hello, World!\n"
    start_response("200 OK", [
        ("Content-Type", "text/plain"),
        ("Content-Length", str(len(data)))
    ])
    return iter([data])
$ gunicorn -w 2 -b 0.0.0.0:8000 myapp:app
2010-08-10 00:03:36 [2706] [INFO] Starting gunicorn 0.10.1
2010-08-10 00:03:36 [2706] [INFO] Listening at: http://0.0.0.0:8000
2010-08-10 00:03:36 [2708] [INFO] Booting worker with pid: 2708
2010-08-10 00:03:36 [2709] [INFO] Booting worker with pid: 2709

Xenで適当にインスタンスを作ってabかけてみる

$ ab -c 100 -n 10000 http://192.168.11.153:8000/
Server Software:        gunicorn/0.10.1
Server Hostname:        192.168.11.153
Server Port:            8000

Document Path:          /
Document Length:        14 bytes

Concurrency Level:      100
Time taken for tests:   10.528 seconds
Complete requests:      10000
Failed requests:        0
Write errors:           0
Total transferred:      1601760 bytes
HTML transferred:       140154 bytes
Requests per second:    949.86 [#/sec] (mean)
Time per request:       105.279 [ms] (mean)
Time per request:       1.053 [ms] (mean, across all concurrent requests)
Transfer rate:          148.58 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        1   52 265.9     26    3051
Processing:     5   36  31.8     30     431
Waiting:        3   28  30.3     22     429
Total:         12   88 268.6     54    3107

Percentage of the requests served within a certain time (ms)
  50%     54
  66%     81
  75%     90
  80%    100
  90%    103
  95%    105
  98%    240
  99%    271
 100%   3107 (longest request)

ちなみに、fapws3だとこんな感じだった。

$ cat myapp2.py
import fapws._evwsgi as evwsgi
from fapws import base

def start():
    evwsgi.start("0.0.0.0", "8000")
    evwsgi.set_base_module(base)

    def app(environ, start_response):
        data = "Hello, World!\n"
        start_response("200 OK", [
            ("Content-Type", "text/plain"),
            ("Content-Length", str(len(data)))
        ])
        return iter([data])

    evwsgi.wsgi_cb(("/", app))
    evwsgi.run()

if __name__ == "__main__":
    start()
Server Software:        fapws3/0.6
Server Hostname:        192.168.11.153
Server Port:            8000

Document Path:          /
Document Length:        14 bytes

Concurrency Level:      100
Time taken for tests:   14.429 seconds
Complete requests:      10000
Failed requests:        0
Write errors:           0
Total transferred:      1360000 bytes
HTML transferred:       140000 bytes
Requests per second:    693.04 [#/sec] (mean)
Time per request:       144.292 [ms] (mean)
Time per request:       1.443 [ms] (mean, across all concurrent requests)
Transfer rate:          92.04 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0   90 471.5      9    9000
Processing:     6   40  28.5     32     309
Waiting:        2   32  26.5     27     308
Total:          7  131 481.1     36    9019

Percentage of the requests served within a certain time (ms)
  50%     36
  66%    106
  75%    113
  80%    113
  90%    115
  95%    116
  98%   3081
  99%   3098
 100%   9019 (longest request)

次、meinheld。

$ cat myapp3.py
from meinheld import server

def app(environ, start_response):
    data = "Hello, World!\n"
    start_response("200 OK", [
        ("Content-Type", "text/plain"),
        ("Content-Length", str(len(data)))
    ])
    return iter([data])

server.listen(("0.0.0.0", 8000))
server.run(app)
Server Software:        meinheld/0.1.2
Server Hostname:        192.168.11.153
Server Port:            8000

Document Path:          /
Document Length:        14 bytes

Concurrency Level:      100
Time taken for tests:   11.143 seconds
Complete requests:      10000
Failed requests:        0
Write errors:           0
Total transferred:      1400000 bytes
HTML transferred:       140000 bytes
Requests per second:    897.44 [#/sec] (mean)
Time per request:       111.429 [ms] (mean)
Time per request:       1.114 [ms] (mean, across all concurrent requests)
Transfer rate:          122.70 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        1   67 419.6      3    3010
Processing:    12   41  32.0     35     712
Waiting:        1   39  32.5     34     712
Total:         12  108 424.4     38    3104

Percentage of the requests served within a certain time (ms)
  50%     38
  66%     43
  75%     52
  80%     57
  90%     90
  95%     96
  98%   3030
  99%   3070
 100%   3104 (longest request)

gunicornでmeinheldのWorkerを使ってみる

$ gunicorn -w 2 --worker-class="meinheld.gmeinheld.MeinheldWorker" -b 0.0.0.0:8000 myapp:app
Server Software:        meinheld/0.1.2
Server Hostname:        192.168.11.153
Server Port:            8000

Document Path:          /
Document Length:        14 bytes

Concurrency Level:      100
Time taken for tests:   10.751 seconds
Complete requests:      10000
Failed requests:        0
Write errors:           0
Total transferred:      1400000 bytes
HTML transferred:       140000 bytes
Requests per second:    930.14 [#/sec] (mean)
Time per request:       107.511 [ms] (mean)
Time per request:       1.075 [ms] (mean, across all concurrent requests)
Transfer rate:          127.17 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        1   67 414.6     16    9016
Processing:     9   30  42.5     21     750
Waiting:        1   28  42.3     19     749
Total:         13   98 417.9     36    9037

Percentage of the requests served within a certain time (ms)
  50%     36
  66%     40
  75%     44
  80%     49
  90%     90
  95%     93
  98%    286
  99%   3038
 100%   9037 (longest request)

Xen上で動かしてるからなのかはわからないけど、全体的にabの結果にばらつきがあった。
少なくともgunicorn自体は遅いとかはないっぽい?運用面で有利だったりするのかな。