中野 宏朗
nakan****@nttco*****
2012年 1月 4日 (水) 10:33:18 JST
中野@幕張です。 sslidの既存のコードですが、一応自分のアルゴリズム通りになっているっぽいので、 既存のコードベースで改善をしてみることにしました。 ・memmoveの除去 →単なるオフセットのためだけにmemmoveしてる。memmoveは内部で2回メモリコピー走るので、 コストがでかい。んなもん、ポインタアドレス書き換えるだけでいい。 ・realserver_selectedのフラグ化 →boostのendpoint型のnullというか、0というか、それの比較のためだけに 型宣言と暗黙の初期化を使って比較している。そのためだけに、パケットくるたびに インスタンス起こすなんて無駄。ほんとはビット演算が一番良いが、他のフラグに あわせてとりあえずint型のflag変数に置き換え。 パフォーマンス低下に支配的なのは、たぶんsslid用mapのロックなんですが、 そこを変えるのは今の設計を大幅に変えることになるので、とりあえず やりやすいところから。 memcopyもすごく無駄なので無くしたいのですが、ここを変えるとなると threaddata->data_bufferを無くして、ポインタ管理に切り替えるような 根本的対処が必要になるので、とりあえず放置・・・ # クライアントから受け取ったデータは、そのまま一度もコピーとかすることなく # リアルサーバ用ソケットにアドレス渡せばいいのに。わざわざメインメモリに # 入出力アクセスしてるから、CPUキャッシュからも外れて遅くなってる。 (2011/12/14 17:46), 中野 宏朗 wrote: > 中野@幕張%別仕事でコードからどんどん離れる・・・です。 > > sslidのパーシステント部分をごっそり無効にしたコードで > 検証しようとしていて、よくわからないコード見つけました。 > > protocol_module_sslid.cpp > protocol_module_sslid::handle_realserver_select( > の > 1517 if (realserver_selected(threaddata->selected_realserver)) { > の中身。 > > 4143 boost::asio::ip::tcp::endpoint temp_endpoint; > 4144 if (temp_endpoint == rs_endpoint) { > > ・・・これ、なにを比較しようとしたいの?temp_endpointの存在意義って・・・ > threaddata->selected_realserverって、どこで入るんだろう・・・ > > あと、 > > 1543 (get_ssl_session_id(threaddata->data_buffer.data() + threaddata->data_begain_offset, > 1544 threaddata->data_size, session_id) == -1)) { > > の中身って、リターンコードは0と1と-1返してるけど、-1しか使ってないよね。 > まあ、 > > 1572 if (session_id.empty()) { > > で見てるんだろうけど。でもC++なら暗黙に初期化されるとはいえ、session_id初期化してないし。 > > コード見て何がしたいのかわかんなかったので、外部設計書とか確認したけど、 > アルゴリズムがRFCベースとは違ってる感じ。 > UltraMonkey使わないときのSSL IDのプロトコルをまずはベースにして、 > そこにUM-L7入れたときにどういう手順にするかしないと。 > > もともとのSSL IDは、RFC2246の7.3節あたり。 > > http://www5b.biglobe.ne.jp/~type-aya/rfc/rfc2246j.txt > > そこにUM-L7を噛ませた場合のアルゴリズムを、もう一度考えてみました。 > ====== > 1. ClientHelloのパケットをupthreadで捕まえる。 > 2. SSLIDが付与されているかどうか、見る。 > 3. 付与されていなければ、スケジュールモジュールによりendpointを決めて、6にいく。 > 4. 付与されていれば、session_endpoint_mapに問い合わせて、endpointをゲットし、6にいく。 > 5. 4でゲットできなければ、session_endpoint_mapにSSLIDとendpointを登録して、3にいく。 > 6. リアルサーバにぶんなげる。 > 7. ServerHelloのパケットをdownスレッドで捕まえる。 > 8. 捕まえたパケットのSSLIDをぶっこ抜く。 > 9. ぶっこ抜いたSSLIDが、upthreadで捕まえたClientHelloのSSLIDを同じかチェックする。 > 10. 同じならば、12にいく。 > 11. 違ったら、session_endpoint_mapの該当endpointのセッションIDのほうを更新する。 > あ、単に追加するだけでもいいか。できれば、古いのを消す。 > 12. クライアントにぶんなげる。 > ====== > > 要は、SSL IDが入っていたら、まずはsession_endpoint_mapを見なければ始まらないはず。 > realserver_selectedって何者なんだ。sslidやmap見る前に格納されるデータに見えないんだけど。 > あと、RFC2246によると、SSLIDがリアルサーバ側でヒットしなければ、Server Helloで > 異なるIDを付与して送ってくるはず。 > そしたら、downthreadでmapを更新しなければいけないはず。その処理ないよね? > > まずは上記アルゴリズム案で直してみようと思いますが、どうでしょう。 > 速度が出るかどうかは未保障w > > つか、session_endpoint_mapをスレッドまたがりのデータとして持って、 > mutex lock掛けながらスレッドが参照しなきゃいけないから、かなり > 遅くなると思う。セッションレスより遅くなるんじゃないかな。 > > session_endpoint_mapをスレッド固有データとして持てるデータ構造というか > 仕組みを考案できたら、速くなるだろうけど。 > > あと問題は、自分がコードいじれるまとまった時間がないってこと・・・ > > (2011/11/11 17:20), 中野 宏朗 wrote: >> 中野@幕張です。 >> >> SSLIDモジュールで通信した時、性能が極端に悪いという事象について、 >> どなたかチケットを発行してもらえないでしょうか。 >> # 自分でやってもいいですが(出来るのかな?)、自分は上記以上の経緯は >> # 知らないので・・・ >> >> で、自分がとりあえず担当しますので、hiroakinakanoにアサイン >> してもらえればと思います。 >> >> ちなみに、まだ糸口はつかめていませんorz >> >> # sslidのhandler系にrdtsc仕掛けてみたんですが、時間かかっているところは >> # 見つからなかったので、ハンドラ内で時間かかっているわけではなさそう。 >> # となると、ハンドラを起動するのに時間かかっている?それだと他の >> # プロトコルでも再現しそうなきもするし・・・ >> >> # 他に固有なところといえば、ssl_protocol_module_base?といっても、 >> # 特定のオフセットのデータをみてるだけだよな〜・・・ >> # ひょっとして、protocolモジュールをVirtualServiceからロードし、 >> # sessionスレッドで呼び出すから、パケットデータであるthreaddataの >> # 参照で、CPU間でメインメモリ介したコピーが走ってる?でもそんなに >> # 影響するかなぁ・・・ >> ## 脳みそ沸騰中 >> > -- 中野 宏朗 (NAKANO Hiroaki) NTTコムウェア 品質生産性技術本部 技術SE部 基盤ソフトSE・OSS部門 OSS適用推進担当 Tel: 043-211-2452 (Ext: 特番+26-8341), Fax: 043-211-5086 Zip/Address: 261-0023 千葉県千葉市美浜区中瀬1-6 NTT幕張ビル21F-En -------------- next part -------------- Index: module/protocol/protocol_module_sslid.cpp =================================================================== --- module/protocol/protocol_module_sslid.cpp (リビジョン 11540) +++ module/protocol/protocol_module_sslid.cpp (作業コピー) @@ -38,6 +38,8 @@ const int protocol_module_sslid::ACCEPT_END_FLAG_ON = 1; // accept flag on const int protocol_module_sslid::SORRY_FLAG_ON = 1; // sorry flag on const int protocol_module_sslid::SORRY_FLAG_OFF = 0; // sorry flag off +const int protocol_module_sslid::SELECTED_FLAG_ON = 1; // realserver selected flag on +const int protocol_module_sslid::SELECTED_FLAG_OFF = 0; // realserver selected flag off //! constructor protocol_module_sslid::protocol_module_sslid() @@ -956,6 +958,7 @@ threaddata_up->sorry_flag = SORRY_FLAG_OFF; // set sorry_flag OFF threaddata_up->end_flag = END_FLAG_OFF; // set end_flag OFF threaddata_up->accept_flag = ACCEPT_END_FLAG_OFF; // set accept_flag OFF + threaddata_up->selected_flag = SELECTED_FLAG_OFF; // set selected_flag OFF threaddata_up->thread_division = THREAD_DIVISION_UP_STREAM; // up thread division threaddata_up->pair_thread_id = down_thread_id; threaddata_up->last_status = ACCEPT; @@ -966,7 +969,7 @@ boost::format formatter("function : protocol_module_base::EVENT_TAG protocol_module_sslid::" "handle_session_initialize() : session_thread_data_sslid(upthread) : " "data_begin_offset = %d, data_size = %d, current_record_rest_size = %d, " - "hello_message_flag = %d, sorry_flag = %d, end_flag = %d, accept_flag = %d, " + "hello_message_flag = %d, sorry_flag = %d, end_flag = %d, accept_flag = %d, selected_flag = %d, " "thread_division = %d, pair_thread_id = %d, last_status = %d."); formatter % threaddata_up->data_begain_offset % threaddata_up->data_size @@ -975,6 +978,7 @@ % threaddata_up->sorry_flag % threaddata_up->end_flag % threaddata_up->accept_flag + % threaddata_up->selected_flag % threaddata_up->thread_division % threaddata_up->pair_thread_id % threaddata_up->last_status; @@ -999,6 +1003,7 @@ threaddata_down->sorry_flag = SORRY_FLAG_OFF; // set sorry_flag OFF threaddata_down->end_flag = END_FLAG_OFF; // set end_flag OFF threaddata_down->accept_flag = ACCEPT_END_FLAG_OFF; // set accept_flag OFF + threaddata_down->selected_flag = SELECTED_FLAG_OFF; // set selected_flag OFF threaddata_down->thread_division = THREAD_DIVISION_DOWN_STREAM; // down thread division threaddata_down->pair_thread_id = up_thread_id; threaddata_down->last_status = REALSERVER_RECV; @@ -1009,7 +1014,7 @@ boost::format formatter("function : protocol_module_base::EVENT_TAG protocol_module_sslid::" "handle_session_initialize() : session_thread_data_sslid(downthread) : " "data_begin_offset = %d, data_size = %d, current_record_rest_size = %d, " - "hello_message_flag = %d, sorry_flag = %d, end_flag = %d, accept_flag = %d, " + "hello_message_flag = %d, sorry_flag = %d, end_flag = %d, accept_flag = %d, selected_flag = %d, " "thread_division = %d, pair_thread_id = %d, last_status = %d."); formatter % threaddata_down->data_begain_offset % threaddata_down->data_size @@ -1018,6 +1023,7 @@ % threaddata_down->sorry_flag % threaddata_down->end_flag % threaddata_down->accept_flag + % threaddata_down->selected_flag % threaddata_down->thread_division % threaddata_down->pair_thread_id % threaddata_down->last_status; @@ -1312,7 +1318,8 @@ /*------DEBUG LOG END------*/ // move the data from data start pos to buffer start pos - memmove(databuf, databuf + threaddata->data_begain_offset, threaddata->data_size); + //memmove(databuf, databuf + threaddata->data_begain_offset, threaddata->data_size); + databuf += threaddata->data_begain_offset; /*-------- DEBUG LOG --------*/ if (unlikely(LOG_LV_DEBUG == getloglevel())) { @@ -1514,7 +1521,8 @@ } // the first connection or connected successful - if (realserver_selected(threaddata->selected_realserver)) { + //if (realserver_selected(threaddata->selected_realserver)) { + if (realserver_selected(threaddata)) { /*-------- DEBUG LOG --------*/ if (unlikely(LOG_LV_DEBUG == getloglevel())) { boost::format formatter("function : protocol_module_base::EVENT_TAG protocol_module_sslid::" @@ -1582,6 +1590,7 @@ if (temp_endpoint != comp_endpoint) { // success for get the endpoint by reschedule threaddata->selected_realserver = temp_endpoint; + threaddata->selected_flag = SELECTED_FLAG_ON; rs_endpoint = temp_endpoint; status = REALSERVER_CONNECT; } else { @@ -1638,6 +1647,7 @@ if (is_match) { // get the endpoint successfully rs_endpoint = threaddata->selected_realserver; + threaddata->selected_flag = SELECTED_FLAG_ON; status = REALSERVER_CONNECT; } else { // failed to get the endpoint @@ -1653,6 +1663,7 @@ if (temp_endpoint != comp_endpoint) { // get the endpoint by reschedule successfully threaddata->selected_realserver = temp_endpoint; + threaddata->selected_flag = SELECTED_FLAG_ON; rs_endpoint = temp_endpoint; status = REALSERVER_CONNECT; } else { @@ -1728,6 +1739,7 @@ if (temp_endpoint != comp_endpoint) { // get the endpoint by reschedule successfully threaddata->selected_realserver = temp_endpoint; + threaddata->selected_flag = SELECTED_FLAG_ON; rs_endpoint = temp_endpoint; status = REALSERVER_CONNECT; } else { @@ -2626,6 +2638,8 @@ /*-------- DEBUG LOG --------*/ if (unlikely(LOG_LV_DEBUG == getloglevel())) { std::string datadump; + // get the c-style pointer from data buffer + //char *databuf = threaddata->data_buffer.c_array(); dump_memory(databuf + threaddata->data_begain_offset, threaddata->data_size, datadump); boost::format formatter("function : protocol_module_base::EVENT_TAG protocol_module_sslid::" @@ -2637,7 +2651,8 @@ /*------DEBUG LOG END------*/ // move the data from data start pos to buffer start pos - memmove(databuf, databuf + threaddata->data_begain_offset, threaddata->data_size); + //memmove(databuf, databuf + threaddata->data_begain_offset, threaddata->data_size); + databuf += threaddata->data_begain_offset; /*-------- DEBUG LOG --------*/ if (unlikely(LOG_LV_DEBUG == getloglevel())) { @@ -4129,19 +4144,20 @@ //! @param[in] endpoint reference //! @return false if endpoint is not selected //! @return true if endpoint is selected -bool protocol_module_sslid::realserver_selected(const boost::asio::ip::tcp::endpoint &rs_endpoint) +bool protocol_module_sslid::realserver_selected(const thread_data_ptr &threaddata) { /*-------- DEBUG LOG --------*/ if (unlikely(LOG_LV_DEBUG == getloglevel())) { boost::format formatter("in_function : bool protocol_module_sslid::realserver_selected(" "const boost::asio::ip::tcp::endpoint& rs_endpoint) : rs_endpoint = [%s]:%d."); - formatter % rs_endpoint.address().to_string() % rs_endpoint.port(); + formatter % threaddata->selected_realserver.address().to_string() % threaddata->selected_realserver.port(); putLogDebug(300169, formatter.str(), __FILE__, __LINE__); } /*------DEBUG LOG END------*/ - boost::asio::ip::tcp::endpoint temp_endpoint; - if (temp_endpoint == rs_endpoint) { + //boost::asio::ip::tcp::endpoint temp_endpoint; + //if (temp_endpoint == rs_endpoint) { + if (threaddata->selected_flag == SELECTED_FLAG_OFF) { /*-------- DEBUG LOG --------*/ if (unlikely(LOG_LV_DEBUG == getloglevel())) { putLogDebug(300170, "out_function : bool protocol_module_sslid::realserver_selected("