休日になると、普段やらないような、つまらないテストをいろいろやってみたくなります。 今回はHTTPの性能を試しました。
以前から多少気になっていた事ですが、 Zope で純粋に読むだけのリクエストを送った場合、 具体的な数値として一秒間に何回ぐらい応答できるのでしょうか。 実務的には必ずApacheやSquidをフロントエンドにして、 Zopeを直接叩くことはないわけですけど、 何とかなく気になった訳です。
クライアントがネックになると困るので、 Cで書きました。 HTTP関連は面倒くさいので、 neon を利用します。 まあ、Apacheのabとかでもいいんですけど、 極力クライアントが負担にならないようにしたかったんで。 プログラムは以下の通り。
#include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <assert.h> #include <ne_socket.h> #include <ne_uri.h> #include <ne_session.h> #include <ne_request.h> static int num; static ne_uri parsed_url; static void * test (void *data) { int i; ne_session *session; session = ne_session_create (parsed_url.scheme, parsed_url.host, parsed_url.port); assert (session); for (i = 0; i < num; i++) { ne_request *request; int ret; int retry; request = ne_request_create (session, "GET", parsed_url.path); assert (request); for (retry = 0; retry < 10; retry++) { ret = ne_request_dispatch (request); if (ret == NE_OK) break; } assert (ret == NE_OK); ne_request_destroy (request); } ne_session_destroy (session); return 0; } int main (int argc, char *argv[]) { int i; int thread_num; pthread_t *threads; char *url; if (argc < 4) { printf ("Usage: httptest THREAD_NUM NUM URL\n"); return 1; } assert (ne_sock_init () == 0); thread_num = atoi (argv[1]); num = atoi (argv[2]); url = argv[3]; assert (ne_uri_parse (url, &parsed_url) == 0); if (parsed_url.port == 0) parsed_url.port = ne_uri_defaultport (parsed_url.scheme); threads = malloc (sizeof (threads[0]) * thread_num); assert (threads); for (i = 0; i < thread_num; i++) { int ret; ret = pthread_create (threads + i, 0, test, 0); assert (ret == 0); } for (i = 0; i < thread_num; i++) { int ret; ret = pthread_join (threads[i], 0); assert (ret == 0); } free (threads); ne_uri_free (&parsed_url); return 0; }
コンパイルは
gcc `neon-config --cflags` -O2 -g -o httptest httptest.c `neon-config --libs`
マシンはPentium M 1.4GHz、メモリ1GBです。 CPUが一個しかないので、真の並行アクセスは実現できませんが、 あまり問題にはならないでしょう。
対象は、何にも調整していないApache 2.0.53です。
$ time ./httptest 100 100 http://localhost/ 0.37user 0.32system 0:04.03elapsed 17%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+1748minor)pagefaults 0swaps $ time ./httptest 100 100 http://localhost/ 0.36user 0.28system 0:04.13elapsed 15%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+1593minor)pagefaults 0swaps $ time ./httptest 100 100 http://localhost/ 0.37user 0.24system 0:04.13elapsed 14%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+1623minor)pagefaults 0swaps
スレッド数100で、各スレッドが100回リクエスト。 クライアントが多少食ってるので、 もうちょっと速いのかもしれませんが、 大体一秒間2400ってとこでしょうか。
Zope 2.8.2の場合。
$ time ./httptest 100 100 http://localhost:8080/ 0.36user 0.23system 1:16.46elapsed 0%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+1266minor)pagefaults 0swaps $ time ./httptest 100 100 http://localhost:8080/ 0.39user 0.21system 1:17.33elapsed 0%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+1257minor)pagefaults 0swaps $ time ./httptest 100 100 http://localhost:8080/ 0.23user 0.12system 1:14.08elapsed 0%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+1512minor)pagefaults 0swaps
いろいろパッチが当たっているので、 ピュアとは言えないZopeなんですが、 大体130というところですね。
というわけで、何にもしないでただ読むだけの場合、 ZopeはApacheより18倍遅いです。
Twisted化されたら、どうなるんだろうとか、 RubyのwebrickやJ2EEだとどうなんだろうとか、 いろいろ興味は尽きないのですが、 こんなところでした。
Zopeは全部動的に解決しているので、 Apacheとは作業量が全然異なりますから、 Zopeはそんなに遅いんだ!とか誤読しないように。
drues uskrgn brkethfy ugnrvtk idwgatpv qopgjfi adwv
hzpveura btskg ksdur ohqrvnyms pgufvc bkolywan krmwpz http://www.mnwsofbzt.cmpuswz.com