4

この質問は、私が過去数日間に尋ねた他の2つの質問の結果です。
送信/受信のフローを制御する方法を理解する上での「次のステップ」に関連していると思うので、新しい質問を作成しています。これについては、まだ完全な答えは得られていません。
その他の関連する質問は次
のとおりです。IOCPドキュメントの解釈に関する質問-バッファの所有権のあいまいさ
非ブロッキングTCPバッファの問題

要約すると、私はWindows I/O完了ポートを使用しています。
完了ポートからの通知を処理するスレッドがいくつかあります。
質問はプラットフォームに依存せず、* nix、* BSD、Solarisシステムで同じことをするのと同じ答えになると思います。

ですから、私は自分のフロー制御システムを持っている必要があります。罰金。
だから私は送信と送信をたくさん送信します。受信側はX量に制限されているため、送信のキューイングをいつ開始するかをどのように知ることができますか?

例を見てみましょう(私の質問に最も近いもの):FTPプロトコル。
私は2台のサーバーを持っています。1つは100Mbリンク上にあり、もう1つは10Mbリンク上にあります。
100Mbをもう一方(10Mbにリンクされたもの)に1GBのファイルを送信するように注文します。平均転送速度は1.25MB/秒で終了します。
送信者(100Mbにリンクされたもの)は、送信を保留するタイミングをどのように知っていたので、遅い送信者がフラッディングされませんでしたか?(この場合、「送信される」キューはハードディスク上の実際のファイルです)。

これを尋ねる別の方法:
リモート側から「送信保留」通知を受け取ることはできますか?TCPに組み込まれているのでしょうか、それともいわゆる「信頼性の高いネットワークプロトコル」である必要がありますか?

もちろん、送信を固定バイト数に制限することもできますが、それは私には正しく聞こえません。

繰り返しになりますが、リモートサーバーへの送信が多いループがあり、そのループ内のある時点で、その送信をキューに入れるか、トランスポート層(TCP)に渡すことができるかを判断する必要があります
それ、どうやったら出来るの?あなたならどうしますか?もちろん、送信が完了したというIOCPからの完了通知を受け取ったら、他の保留中の送信を発行します。これは明らかです。

これに関連する別の設計上の質問:
送信キューでカスタムバッファを使用するため、「送信完了」通知が到着したときにこれらのバッファは解放されて再利用されます(したがって、「delete」キーワードは使用されません)。 、そのバッファプールで相互除外を使用する必要があります。
ミューテックスを使用すると処理が遅くなるので、私は考えていました。各スレッドに独自のバッファプールを持たせないのはなぜですか。したがって、少なくとも送信操作に必要なバッファを取得するときにアクセスする場合、スレッドのみに属するため、ミューテックスは必要ありません。
バッファープールは、スレッドローカルストレージ(TLS)レベルにあります。
相互プールがないということは、ロックが不要であることを意味し、操作が高速であることを意味しますが、一方のスレッドがすでに1000個のバッファーを割り当てている場合でも、現在送信中で、何かを送信するために1000個のバッファーが必要なもう一方のスレッドは、割り当てる必要があるため、アプリによって使用されるメモリも多くなります。これらを独自に。

別の問題:
「送信予定」キューにバッファA、B、Cがあるとします。
次に、受信者が15バイトのうち10バイトを取得したことを通知する完了通知を受け取ります。バッファの相対オフセットから再送信する必要がありますか、それともTCPがそれを処理しますか、つまり送信を完了しますか?また、必要に応じて、このバッファがキュー内の「次に送信される」バッファであると確信できますか、それともたとえばバッファBである可能性がありますか?

これは長い質問であり、誰もけがをしなかったことを願っています(:

誰かがここで答えるのに時間がかかるのを見てみたいです。私は彼に二重投票することを約束します!(:
ありがとうございました!

4

3 に答える 3

3

まず、これを別の質問として質問します。そうすれば答えが得られる可能性が高くなります。

私は私のブログでこれについてほとんど話しました:http://www.lenholgate.comしかし、あなたはすでに私のブログを読んだと言って私に電子メールを送ったので、あなたはそれを知っています...

TCPフロー制御の問題は、非同期書き込みを投稿しているため、これらはそれぞれ、完了するまでリソースを使用するというものです(ここを参照)。書き込みが保留されている間、注意すべきさまざまなリソース使用の問題があり、データバッファの使用はそれらの中で最も重要ではありません。また、有限のリソースである非ページプールを使い果たします(ただし、Vista以降では、以前のオペレーティングシステムよりもはるかに多くのリソースが利用可能です)。また、書き込み中はページをメモリにロックします。 OSがロックできるページの総数の制限。非ページプールの使用法とページロックの問題はどちらも、どこでも十分に文書化されているものではないことに注意してください。ただし、ENOBUFSにヒットすると、書き込みが失敗することがわかります。

これらの問題があるため、制御できない数の書き込みを保留にすることは賢明ではありません。大量のデータを送信していて、アプリケーションレベルのフロー制御がない場合は、接続のもう一方の端で処理できるよりも速く、またはリンク速度よりも速くデータを送信する場合は、次に、TCPフロー制御とウィンドウ処理の問題のために書き込みが完了するまでに時間がかかるため、上記のリソースを大量に使い始めることになります。フロー制御の問題のためにTCPスタックがそれ以上書き込みできない場合、書き込み呼び出しは単にブロックするため、ソケットコードのブロックでこれらの問題は発生しません。asyncを使用すると、書き込みが完了し、保留になります。ブロッキングコードを使用すると、ブロッキングはフロー制御を処理します。

とにかく、このため、Windowsの非同期I / Oでは、常に何らかの形式の明示的なフロー制御が必要です。したがって、おそらくACKを使用して、アプリケーションレベルのフロー制御をプロトコルに追加します。これにより、データが反対側に到達したことを認識し、一度に特定の量だけが未処理になるようにするか、追加できない場合にアプリケーションレベルのプロトコルでは、書き込み完了を使用して物事を推進できます。秘訣は、接続ごとに一定数の未処理の書き込み完了を許可し、制限に達したらデータをキューに入れる(またはデータを生成しない)ことです。次に、各書き込みが完了すると、新しい書き込みを生成できます。

データバッファのプールについてのあなたの質問は、私見、あなたの側での時期尚早の最適化です。システムが適切に機能し、システムのプロファイルを作成し、バッファープールでの競合が最も重要なホットスポットであることがわかった時点で、それに対処します。スレッドごとのバッファープールはうまく機能せず、スレッド間での割り当てと解放の分散は、機能するために必要なほどバランスが取れていない傾向があることがわかりました。私は私のブログでこれについてもっと話しました:http: //www.lenholgate.com/blog/2010/05/performance-comparisons-for-recent-code-changes.html

部分的な書き込みの完了(100バイトを送信すると、完了が返され、95を送信しただけだと言う)についての質問は、実際のIMHOでは実際には問題ではありません。この位置に到達し、未処理の書き込みが複数ある場合は、何もできません。後続の書き込みはうまく機能する可能性があり、送信する予定のバイトが欠落している可能性があります。しかし、a)上記で詳述したリソースの問題にすでに遭遇していない限り、これが発生するのを見たことがありません。b)そこにあります。

次回は別の質問をお願いします。

于 2010-06-14T10:38:54.393 に答える
1

Q1。ほとんどのAPIは、最後に書き込んだ後、書き込みが再び利用可能になった後、「書き込みが可能」イベントを提供します(送信バッファーの大部分を最後の送信で満たすことができなかった場合、すぐに発生する可能性があります)。

完了ポートを使用すると、「新しいデータ」イベントと同じように到着します。新しいデータを「読み取りOK」と考えると、「書き込みOK」イベントもあります。名前はAPI間で異なります。

Q2。データのチャンクごとのミューテックス取得のカーネルモード遷移が問題になる場合は、何をしているかを再考することをお勧めします。スレッドスケジューラスライスはWindowsでは60ミリ秒にもなる可能性がありますが、最大で3マイクロ秒かかります。

極端な場合は傷つくことがあります。あなたが極端なコミュニケーションをプログラミングしていると思うなら、もう一度尋ねてください、そして私はあなたにそれについてすべて話すことを約束します。

于 2010-06-13T22:00:04.967 に答える
1

速度が低下することがわかった時期についての質問に対処するには、TCP輻輳メカニズムについての理解が不足しているようです。「スロースタート」はあなたが話していることですが、それはあなたがそれをどのように表現したかではありません。スロースタートとは、まさにそのことです。最初はゆっくりと始まり、もう一方の端が進んでいく速度まで、ワイヤラインの速度など、速くなります。

残りの質問に関しては、Pavelの答えで十分です。

于 2010-06-13T22:02:28.243 に答える