为什么阻止UdpClient.Receive大大增加了cpu的使用?

时间:2014-06-19 01:00:21

标签: .net performance sleep udpclient

我认为我优化了以下代码,因为当没有可用数据时它会Sleep(1),因此会产生高达15.6毫秒的延迟(生产中盒子上的实际计时器分辨率) ,浪费时间睡觉,而它可能正在处理数据包。

while (running)
{
  int available = _udpClient.Available;
  if (available > 0)
  {
    byte[] packet = _udpClient.Receive(ref serverEndPoint);
    _concurrentJobQueue.Enqueue(packet);
    if (available > x)
      LogSomething(available);
  }
  else
  {
    Thread.Sleep(1);
  }
}

由于UdpClient提供了阻止Receive(),这看起来很容易:

while (running)
{
  byte[] packet = _udpClient.Receive(ref serverEndPoint);
  _concurrentJobQueue.Enqueue(packet);
  int available = _udpClient.Available;
  if (available > x)
    LogSomething(available);
}

现在Receive()应该正在进行所有休眠,如果有效实施,它会在数据包到达时立即唤醒。

这应该

  • 稍微减少cpu密集度,因为没有不必要的旋转(根据计时器分辨率,最多1000次/秒)
  • 消除睡眠延迟

然而,当以每秒10k的速率发送100k数据包时,"优化&#34>版本比原始版本密集得多 - 以下结果来自于计时器分辨率为1毫秒的机器上的测试,因此原始版本仅为"仅#34;如果没有可用数据包,则睡1ms:

test case     avg cpu (%)
------------+------------
original      0.81427075
"optimized"   16.8082852

为什么阻止Receive()阻塞cpu的次数超过20次?

注意:

  • 我仔细检查了两种情况下处理的数据包的数量大致相同,即优化版本消耗了更多cpu的原因并不是原始版本由于UDP缓冲区溢出而需要处理的数据包较少< / LI>
  • 我们总共有50个UdpClient个,每个UdpClient的1个主题正在运行上述while循环
  • 试图分析&#34;优化&#34; Visual Studio中的版本使得系统在崩溃时托管的Virtual Box VM
  • 在具有不同计时器分辨率(1或15.6)的物理机器上进行测试显示定性相似的结果
  • 即使在15.6ms定时器分辨率的盒子上,盒子也能顺利跟上传入的数据包,并且原始版本的总处理时间与&#34;优化的&#34;相同。 case(我还没有检查单个数据包的延迟,这在应用程序内部很难做到,因为Sleep会影响我创建&#34;传入时间戳的时间&# 34)

0 个答案:

没有答案