From nakai.norihisa @ yes.nttcom.ne.jp Fri May 25 10:43:19 2007 From: nakai.norihisa @ yes.nttcom.ne.jp (=?ISO-2022-JP?B?GyRCQ2Y1bzd7NVcbKEI=?=) Date: Fri, 25 May 2007 10:43:19 +0900 Subject: [Ultramonkey-l7-develop 12] =?iso-2022-jp?b?VWx0cmFNb25rZXktTDcbJEIkTiQzJGwkKyRpJE4zK0gvGyhC?= =?iso-2022-jp?b?GyRCJEskRCQkJEYbKEI=?= Message-ID: <46563F37.9070005@yes.nttcom.ne.jp> NTTComwareでUltraMonkey-L7の開発をしている中居と申します。 以後、よろしくお願いいたします。 さて、今現在のUltraMonkey-L7の次の部分を改良しようと思っております。 順に説明させていただきます。 1.l7syncd 現在 l7syncd同士が通信をし、l7vsdとl7syncdがsharedmemoryを利用して同期するデータをやり取りしている。 [問題点] ・protomod_c*系で1処理ごとにsem_init()やshm_init()を実行して共有メモリにデータを書き込むため、 パフォーマンス的に不利となる。 ・UDPでデータをやり取りしているが、UDPはパケット順序が保障されないにもかかわらず、受け取った順序で 共有メモリに書き込んでいるため、古いデータでsyncされる危険性がある ・パケットサイズを考慮しておらず、パケット分割が発生した場合にデータが破損する可能性がある(MTUサイズによる)。 [解決案] ・共有メモリを使用しない方式に変更する必要があると思われる。 ・どのタイミングで同期化するのか検討が必要 2.sorryサーバへの振り分け [問題点] ・protomod_c*モジュール中のmatch_cldata()で共有メモリの情報を参照するために速度的な問題がある ・また、match_cldata()で判定後にiomのdestを直接書き換えている。 ・共有メモリ中の判定状況を戻す手段が無い [解決案] ・各clientにリアルサーバの接続を振り分けるsched部分がsorryサーバの振り分け機能を受け持つのが妥当と考える。 3.振り分け機能 [追加機能] ・リアルサーバにはweightの値があるため、それを利用して振り分けるschedモジュールを作成する。 4.select -> epoll化 [考察] epollに関してはEdgeTriggerとLevelTriggerが存在する。それぞれのメリットデメリットは LTでは現在の構造的に無理なくマッチングされるが、FDの配列を走査する必要があり、betterではあるが bestではない。 ETでは、イベントにマッチしたFD配列をkernelが提供してくれるため、FDの配列を走査する必要が無い。 また、回線の切断などの回線異常もepoll_wait()のイベントとして捕捉可能なため異常処理が上位で捕捉可能になり、 コード的に見通しが良くなり、メモリリークの可能性が減る。 ただし、バッファより大きなデータがTCP/IPスタックに来た場合には一度に全部読むのではなく、 複数回にわたって読み込む場合には再度イベント登録する必要があり、その部分のコストがかかる。 [実験] 上記考察より、以下の実験を行ってみました。 1)epollとselectの速度比較 サーバ側はepollとselectの2種類を作成する。 サーバ側のプログラムは接続しているコネクションからデータを読み出すのみ(そのまま捨てる)。 クライアント側はepollとselectとも共通で指定分のthreadをcreateし、各threadはサーバに接続を行い、 pthread_wait()で待ちの状態に入る。親threadは子threadが全てpthread_wait()に入った段階で、 ptthread_cond_broadcast()を投げて一斉にサーバに対して64kのデータを送信して終了する。 各threadがpthread_wait()から抜けた状態の時間とsend()から戻ってきた時間を合算してベンチとする。 Connectionを別時間とすることで純粋にsend()する時間を計測する。socketはnonblockingに設定。 なお、計測はRDTSC命令を使い分解度をクロックとしてある。 結果 epollを使用したサーバの場合 [root @ um01 client]# ./testClient 1000 Time : 22782330 [root @ um01 client]# ./testClient 1000 Time : 22991643 [root @ um01 client]# ./testClient 1000 Time : 21260133 平均クロック(平均時間):22344702 (0.006982719sec) selectを使用したサーバの場合 [root @ um01 client]# ./testClient 1000 Time : 28468971 [root @ um01 client]# ./testClient 1000 Time : 30799269 [root @ um01 client]# ./testClient 1000 Time : 30726819 平均クロック(平均時間):29998353 (0.009374485sec) おおよそ30%の性能改善が見られる。 2)epollをETで使用した場合にepoll_ctl()でイベントを再登録するときのコスト これは上記サーバプログラムでepoll_ctl()の前後で時間計測をした。 結果:平均クロック数:14419.53(=4.5nsec) [結果考察] selectからepollへの変更は1.3倍の待ち受け部分の性能向上が見込まれる。 またepoll_ctlの処理コストも少ないことから、現状connで回線異常を検出し、protomod*系で判断したのち、 imouxでコネクション等を削除している部分がすべてiomuxで完結するメリットは大きいと考える。 また、現在iomux_listでfdを管理しているが、epoll自体がfdの集合管理を行うため、 iomux_listの走査が不要になり、この部分でのコードの単純化、及びメモリリークの可能性が減る。 以上、現状4つについて考察と試験結果を書かせていただきました。 上記案について、意見等ありましたらご指摘いただけると幸いです。 どうぞよろしくお願いいたします。