2005-12-26

_ HTTPの性能を測ってみる

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

本日のツッコミ(全2件) [ツッコミを入れる]
_ ilfam epfrozjk (2007-03-07 09:09)

drues uskrgn brkethfy ugnrvtk idwgatpv qopgjfi adwv

_ hfxwvly kugaznb (2007-03-07 09:09)

hzpveura btskg ksdur ohqrvnyms pgufvc bkolywan krmwpz http://www.mnwsofbzt.cmpuswz.com

[]