非同期モードで cpp-netlib を使用して、C++ で Ubuntu 14.04 で Web サービスを開発しています。サービスは、メッセージ本文で HTTP POST を介して送信されたデータに応答する必要があります。1K を超える入力を受信するとパフォーマンスが低下することがわかりました。これを修正したいと考えています。
データが 1K 未満の比較的小さい場合、サーバーはほぼ瞬時にデータを受信します。データが 1K を超える場合、実際のデータの最初のチャンクがコールバックに提示される前に、非同期読み取りコールバック関数が最初に呼び出されてから約 1 秒の遅延があります。最初の遅延の後、後続のチャンクがほぼ瞬時に到着します。
この遅延を解消するにはどうすればよいですか? curl を使用してテスト データを投稿した場合のアーティファクトですか? データを投稿するためのcurlのパフォーマンスを簡単にテストするにはどうすればよいですか?
github で問題を示す最小限のソース コードを見つけることができます。サーバーにデータを投稿するために使用するコマンドは次のとおりです。
rcook$ curl -d @AsyncDaemon.h http://localhost:8787/foo
その出力の例を次に示します (注釈付き)。
rcook$ ./async_daemon
1431387368.321863: AsyncDaemon constructor
1431387368.322446: receive thread beginning
*** It's waiting for a connection here.
1431387371.536191: begin transaction 0 on thread 24050
1431387371.536237: transaction 0 constructor
1431387371.536273: received 1206 byte request for /foo from 127.0.0.1:49402
1431387371.536312: invoked asynchronous read
1431387371.536321: end transaction handler
1431387371.536335: begin asynchronous read callback on thread 24050
1431387371.536348: read 0 bytes
1431387371.536386: invoked asynchronous read
1431387371.536394: end asynchronous read callback
*** The asynchronous read callback is invoked quickly, but gets no data.
*** There is then a pause of just over one second before the asynchronous
*** read callback is invoked again.
1431387372.537203: begin asynchronous read callback on thread 24050
1431387372.537253: read 1024 bytes
1431387372.537307: invoked asynchronous read
1431387372.537317: end asynchronous read callback
*** There is no significant delay when reading the next chunk.
1431387372.537429: begin asynchronous read callback on thread 24050
1431387372.537469: read 182 bytes
1431387372.537478: finished reading the body
1431387372.537746: wrote response
1431387372.537763: transaction 0 destructor
1431387372.537772: end asynchronous read callback
*** The server is then killed with a keyboard interrupt.
^C1431387375.382186: terminating with signal 2
1431387375.382231: initiating shutdown
1431387375.382241: stopping server
1431387375.382363: server run finished
1431387375.382423: receive thread ending
1431387375.382522: AsyncDaemon destructor
ご覧のとおり、非同期読み取りコールバックが初めて呼び出された後 (およびゼロ バイトのデータを受信した後)、入力の別のチャンクが要求されます。この時点で、この例では 1431387371.536394 から 1431387372.537203 まで、入力が到着する前に 1 秒強の一時停止があります。その間、何が起こっているのですか?その遅延をなくすにはどうすればよいですか?
オンラインでいくつかの調査を行い、いくつかの実験 (cpp-netlib を使用した同期モードと非同期モード (効果なし)、curl と libcurl (効果なし)) を実行しましたが、答えを見つけることができませんでした。
更新: TCP ダンプ
jxh の提案により、サンプル トランザクション中に tcp ダンプを実行しました。
00:28:01.304446 IP6 localhost.52265 > localhost.8787: Flags [S], seq 3956487146, win 43690, options [mss 65476,sackOK,TS val 395479802 ecr 0,nop,wscale 7], length 0
00:28:01.304461 IP6 localhost.8787 > localhost.52265: Flags [R.], seq 0, ack 3956487147, win 0, length 0
00:28:01.305014 IP localhost.49421 > localhost.8787: Flags [S], seq 1668603425, win 43690, options [mss 65495,sackOK,TS val 395479803 ecr 0,nop,wscale 7], length 0
00:28:01.305039 IP localhost.8787 > localhost.49421: Flags [S.], seq 4010788604, ack 1668603426, win 43690, options [mss 65495,sackOK,TS val 395479803 ecr 395479803,nop,wscale 7], length 0
00:28:01.305079 IP localhost.49421 > localhost.8787: Flags [.], ack 1, win 342, options [nop,nop,TS val 395479803 ecr 395479803], length 0
00:28:01.305185 IP localhost.49421 > localhost.8787: Flags [P.], seq 1:176, ack 1, win 342, options [nop,nop,TS val 395479803 ecr 395479803], length 175
00:28:01.305210 IP localhost.8787 > localhost.49421: Flags [.], ack 176, win 350, options [nop,nop,TS val 395479803 ecr 395479803], length 0
00:28:02.306555 IP localhost.49421 > localhost.8787: Flags [P.], seq 176:1382, ack 1, win 342, options [nop,nop,TS val 395480053 ecr 395479803], length 1206
00:28:02.306620 IP localhost.8787 > localhost.49421: Flags [.], ack 1382, win 1373, options [nop,nop,TS val 395480053 ecr 395480053], length 0
00:28:02.307223 IP localhost.8787 > localhost.49421: Flags [P.], seq 1:52, ack 1382, win 1373, options [nop,nop,TS val 395480053 ecr 395480053], length 51
00:28:02.307270 IP localhost.49421 > localhost.8787: Flags [.], ack 52, win 342, options [nop,nop,TS val 395480053 ecr 395480053], length 0
00:28:02.307494 IP localhost.8787 > localhost.49421: Flags [P.], seq 52:66, ack 1382, win 1373, options [nop,nop,TS val 395480053 ecr 395480053], length 14
00:28:02.307522 IP localhost.49421 > localhost.8787: Flags [.], ack 66, win 342, options [nop,nop,TS val 395480053 ecr 395480053], length 0
00:28:02.307765 IP localhost.8787 > localhost.49421: Flags [F.], seq 66, ack 1382, win 1373, options [nop,nop,TS val 395480053 ecr 395480053], length 0
00:28:02.307867 IP localhost.49421 > localhost.8787: Flags [F.], seq 1382, ack 67, win 342, options [nop,nop,TS val 395480053 ecr 395480053], length 0
00:28:02.307917 IP localhost.8787 > localhost.49421: Flags [.], ack 1383, win 1373, options [nop,nop,TS val 395480053 ecr 395480053], length 0
私は tcpdump の経験があまりありませんが、175 バイトがサーバー (HTTP ヘッダー?) に流れ、1 秒強の遅延の後、1206 バイトがサーバーに流れ、その後に 51 バイトのチャンクが続きます。最小限の遅延に続いて、サーバーの応答が続きます。
これは、おそらくカールで、クライアント側で遅延が発生していることを示しています。誰かが理由を知っていますか?