UDPマルチキャスト伝送速度を調整するために.NETアプリでマイクロ秒の遅延が必要
質問
C#でUDPマルチキャストクライアント/サーバーペアを作成していますが、サーバーの送信レートを調整するには、50〜100秒(マイクロ秒)程度の遅延が必要です。これは、重大なパケット損失を回避するのに役立ち、ディスクI / Oにバインドされているクライアントに過負荷をかけないようにするのにも役立ちます。 Thread.SleepまたはThread.SpinWaitを提案しないでください。どちらかが必要かどうかは尋ねません。
最初に考えたのは、ある種の高性能カウンターを使用して経過時間をチェックする単純なwhile()ループを実行することでしたが、気味が悪いのでそれを避けたいと思います。サーバープロセスのCPU使用率も固定しませんか?
クロスプラットフォームソリューション、つまりWindows固有ではないことに対するボーナスポイント。よろしくお願いします、みんな!
解決
stopwatch を使用しますが、ループ
こちらを読むElapsedMicrosecondsなどのストップウォッチに拡張機能を追加する
またはこのようなものも動作する可能性があります
System.Diagnostics.Stopwatch.IsHighResolution MUST がtrue
static void Main(string[] args)
{
Stopwatch sw;
sw = Stopwatch.StartNew();
int i = 0;
while (sw.ElapsedMilliseconds <= 5000)
{
if (sw.Elapsed.Ticks % 100 == 0)
{ i++; /* do something*/ }
}
sw.Stop();
}
他のヒント
通常、非常に短いスリープ時間は、CPUスピンループ(説明したようなもの)によって最もよく達成されます。通常、高精度のタイマーコールは時間を浪費して結果を歪める可能性があるため、使用を避ける必要があります。このような短い待機時間でサーバーのCPUがペギングすることについてはあまり心配しません。
次のように、動作をクラスにカプセル化します。
- 静的コンストラクターが数百万回の反復に対してスピンループを実行し、所要時間をキャプチャするクラスを作成します。これにより、基礎となるハードウェアで単一のループサイクルがどれくらいかかるかがわかります。
- 任意のスリープ時間の計算に使用できるuS / iteration値を計算します。
- 特定の期間スリープするように求められたら、実行するループ反復の数を識別するために、以前に計算されたuS /反復値でuSをスリープに除算します。
- 推定時間が経過するまで、whileループを使用してスピンします。
マルチキャストアプリケーションでより高い精度が必要なときに、このような要件を経験しました。
この例。
この実装を使用し、TPL非同期呼び出しを追加しました。詳細については、私の SimpleMulticastAnalyzer プロジェクトをご覧ください。
static void udelay(long us)
{
var sw = System.Diagnostics.Stopwatch.StartNew();
long v = (us * System.Diagnostics.Stopwatch.Frequency )/ 1000000;
while (sw.ElapsedTicks < v)
{
}
}
static void Main(string[] args)
{
for (int i = 0; i < 100; i++)
{
Console.WriteLine("" + i + " " + DateTime.Now.Second + "." + DateTime.Now.Millisecond);
udelay(1000000);
}
}
マルチメディアタイマーを見ましたか?おそらく、どこかでAPI呼び出しをラップする.NETライブラリを見つけることができます。
スピンループを使用し、ブロッキングスレッドを作成するため、スピンループの使用はお勧めしません。 thread.sleepの方が優れています。スリープ中はプロセッサリソースを使用せず、時間をスライスします。試してみると、タスクマネージャーからスピンループでCPU使用率が急上昇していることがわかります。