« Pathtraq 最新ランキング ガジェットを公開しました | メイン | Q4M (Queue for MySQL) 0.3 リリース »

2008年03月10日

高速なCometサーバを書いてみた件

 もう昨年の2月になりますが、Comet について調査を行いました。その際の成果をまとめたスライドは既に公開していた (Comet の正しい使い方) のですが、同時に実際に作ってみた実装についても、オープンソース化することとなりました。コードは CodeRepos に置いておきますので、どうぞご覧ください。 (Revision 7754: /lang/perl/fastr)

 使い方は example ディレクトリ以下を見ていただくとして、ベンチマークの結果とチューニング手法について、記録と記憶に残っている範囲からまとめておきたいと思います。

パフォーマンスについて

 まず、パフォーマンスについてですが、Opteron 240EE という今となっては古い CPU でも、同時2,000クライアント程度まではハンドリングできたようです。手元のデータでは、以下の条件 (たぶん実際のチャットサービスよりも厳しいはず) で、CPU 負荷が 80%-90% でした。また、スループットは約 1.6 message/sec.room でした。

測定環境 Opteron 240EE / CentOS 4
受信並列度 2000クライアント (遅延: 0.1〜1.0秒 一様分布)
送信並列度 50クライアント (1秒間隔で送信)
ルーム数 25 (1ルームあたり40クライアント)

 一方、こちらは、より古い CPU (Celeron @ 533MHz) で測定したグラフです。こちらは、全員が単一のルームに入っているという想定でのパフォーマンス測定になります。各グラフは、受信数、送信数、レイテンシについて、送受信の並列度を変えながら測定しています。これらグラフから、送信量ではなく、接続しているクライアントの数がパフォーマンスの律速条件となっていること、また、この環境では400クライアント程度が限界である (レイテンシの目標値を1秒以下と設定した場合) ということが読み取れます。

Fastr パフォーマンスグラフ

チューニング手法について

本サーバについては、Perl で書くことを前提に、以下のようなチューニングを行いました。C で書き直せばもっと速くなるんじゃないかと思います。

  • リバースプロキシとして設計
    • メッセージの転送のみに特化
    • 認証等はバックエンドに中継
  • 可能な限り O(1)
    • ハッシュではなく配列を使う
      • 接続のファイルデスクリプタを添字にする
  • ビットアレイのリングバッファによるタイムアウト処理
    • タイムアウトの設定が O(1)
    • タイムアウトの処理は O(n) だがビットアレイの探索なので高速
    • ビットアレイとリングバッファの大きさは起動時に計算可能
  • HTTP レスポンス全体をキャッシュして使い回し
    • システムコールと memcpy をできるだけ少なく
    • perl は writev をサポートしていない

そんなところです。お楽しみいただければ幸いです。

投稿者 kazuho : 2008年03月10日 15:08 このエントリーを含むはてなブックマーク このエントリーを含むはてなブックマーク

トラックバック

このエントリーのトラックバックURL:
http://labs.cybozu.co.jp/cgi-bin/mt-admin/mt-tbp.cgi/1802