.NET 应用程序中需要微秒延迟来限制 UDP 多播传输速率
题
我正在用 C# 编写一个 UDP 多播客户端/服务器对,我需要大约 50-100 µsec(微秒)的延迟来限制服务器传输速率。这有助于避免严重的数据包丢失,也有助于防止受磁盘 I/O 限制的客户端过载。请不要建议使用 Thread.Sleep 或 Thread.SpinWait。我不会问我是否需要其中任何一个。
我的第一个想法是使用某种高性能计数器并执行一个简单的 while() 循环来检查经过的时间,但我想避免这样做,因为它感觉很笨拙。这是否也会影响服务器进程的 CPU 利用率?
跨平台解决方案的奖励积分,即不是 Windows 特定的。预先感谢各位!
解决方案
我会使用秒表,但需要一个环
阅读此添加更多延伸到秒表,如ElapsedMicroseconds
或类似的东西也可以起作用
System.Diagnostics.Stopwatch.IsHighResolution 必须是真的
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 to sleep 除以之前计算的 uS/iteration 值,以确定要执行的循环迭代次数。
- 使用 while 循环旋转,直到预计时间过去。
当我需要更高精度的多播应用程序时,我遇到了这样的要求。
我发现最好的解决方案在于MultiMedia定时器,如这个例子。
我已经使用了这个实现并添加了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使用率如何与旋转循环一起激增。