gevent はコルーチンベースのネットワークプログラミングライブラリです。 主に大量の同時接続を扱う必要がある場面において力を発揮し、 効率の良いプログラムを簡単に書くことができます。
本セッションでは、 gevent の仕組み、他の仕組みに比べた gevent の長所、 そして gevent によるプログラミングについて解説します。
| export PATH=/opt/local/bin:/opt/local/sbin:/usr/local/bin:$PATH | |
| export PATH=$HOME/bin:$HOME/local/bin:$PATH | |
| # If not running interactively, don't do anything | |
| [ -z "$PS1" ] && return | |
| # virtualenv | |
| export VIRTUALENVWRAPPER_PYTHON=/opt/local/bin/python2.7 | |
| export VIRTUALENV_DISTRIBUTE=1 | |
| source /opt/local/bin/virtualenvwrapper.sh-2.7 |
実行するには python benchmark.py yapc2012.py のようにします。
この benchmark スクリプトは PrimeWars で計測のために使われているものです。
| import heapq | |
| def astar(start, goal, nexts, | |
| distance=len, | |
| heuristic=lambda pos: 0): | |
| hpush = heapq.heappush | |
| hpop = heapq.heappop | |
| queue = [] | |
| checked = set([start]) | |
| hpush(queue, (distance([start]) + heuristic(start), [start])) |
| { | |
| "bench": { | |
| "bytes": 4896760000, | |
| "fetches": 168446, | |
| "max parallel": 10, | |
| "mean bytes/connection": 29070.2, | |
| "msecs/connect": { | |
| "max": 7.445, | |
| "mean": 0.307247, | |
| "min": 0.095 |
| from meinheld import server, patch | |
| patch.patch_socket() | |
| import greenlet | |
| main_greenlet = greenlet.getcurrent() | |
| import redis | |
| def sleep(sec): | |
| server.schedule_call(greenlet.getcurrent().switch) |
| @@ -1203,9 +1201,17 @@ accept_callback(picoev_loop* loop, int fd, int events, void* cb_arg) | |
| remote_port = ntohs(client_addr.sin_port); | |
| client = new_client_t(client_fd, remote_addr, remote_port); | |
| init_parser(client, server_name, server_port); | |
| - ret = picoev_add(loop, client_fd, PICOEV_READ, keep_alive_timeout, read_callback, (void *)client); | |
| - if(ret == 0){ | |
| - activecnt++; | |
| + { | |
| + int finish = read_request(loop, client_fd, client); | |
| + if (finish) { |
| #0 set_bad_request_code (status_code=408, client=<optimized out>) at meinheld/server/server.c:451 | |
| #1 set_read_error (status_code=408, client=0x8e16e0) at meinheld/server/server.c:988 | |
| #2 read_timeout (client=0x8e16e0, fd=<optimized out>) at meinheld/server/server.c:1004 | |
| #3 read_callback (loop=0xa9d760, fd=9, events=4, cb_arg=0x8e16e0) at meinheld/server/server.c:1153 | |
| #4 0x00007ffff6de4642 in picoev_handle_timeout_internal (loop=<optimized out>) at meinheld/server/picoev.h:370 | |
| #5 picoev_loop_once (loop=0xa9d760, max_wait=<optimized out>) at meinheld/server/picoev.h:395 | |
| #6 meinheld_run_loop (self=<optimized out>, args=<optimized out>, kwds=<optimized out>) at meinheld/server/server.c:1672 | |
| #7 0x00000000004a56cd in call_function (oparg=<optimized out>, pp_stack=0x7fffffffe100) at Python/ceval.c:4021 | |
| #8 PyEval_EvalFrameEx (f=f@entry=0x858480, throwflag=throwflag@entry=0) at Python/ceval.c:2666 | |
| #9 0x000000000049fcfb in PyEval_EvalCodeEx (co=co@entry=0x7ffff7eff3b0, globals=globals@entry=0x7fd160, locals=lo |
| Tasks: 73 total, 2 running, 71 sleeping, 0 stopped, 0 zombie | |
| %Cpu(s): 18.0 us, 45.1 sy, 0.0 ni, 12.4 id, 0.0 wa, 0.0 hi, 24.5 si, 0.0 st | |
| KiB Mem: 2050292 total, 1566960 used, 483332 free, 44652 buffers | |
| KiB Swap: 3906556 total, 104 used, 3906452 free, 1341396 cached | |
| PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND | |
| 13641 root 20 0 63892 4740 1796 R 99.5 0.2 0:08.25 ab | |
| 13536 inada-n 20 0 33496 7352 2060 S 74.2 0.4 0:13.76 python |
| #kmemcached | |
| [ec2-user@ip-10-161-30-84 ~]$ ./mcb -cget -t20 -n50000 -p 11212 | |
| condition => | |
| connect to 127.0.0.1 TCP port 11212 | |
| command = get | |
| 20 thread run | |
| send 50000 command a thread, total 1000000 command | |
| data length = 1024 | |
| result => | |
| interval = 3.765747 [sec] |