休日になると、普段やらないような、つまらないテストをいろいろやってみたくなります。 今回は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