W2K3E 系统 CPU 使用率出现无法解释的周期性高峰

W2K3E 系统 CPU 使用率出现无法解释的周期性高峰

我们有一台运行自定义工作负载的 Windows 2003 R2 Enterprise 64 位服务器,它遇到了奇怪的性能问题。下面的精简版遇到的问题较少,但质量上是一样的。

我们将其简化为一个简单的小应用程序,其功能仅包括:

  • 监听套接字
  • 加入多播组
  • 监听进入该组的数据包
  • 读取并丢弃数据包

测试应用程序本身是Boost ASIO 多播接收器示例,所以实际上应该不会出现太多错误。实际代码如下……

在负载下运行此程序时,该进程的 CPU 会不时地加速,因为内核代码中会发生所有的处理:

性能图 (这里仅显示 CPU 6。在此测试期间(3 小时 17 分钟),所有其他处理器都处于空闲状态)

从图中可以看出,当负载达到峰值时,所有的处理时间都发生在内核代码中。所花费的时间大部分花在延迟过程调用(最大 16.8%)和处理中断(最大 8.5%)上。看起来有某种延迟清理正在发生,但我们不知道它是什么。

据我们所知,它仅发生在 W2K3E-64 上。

它发生在不同的硬件上(HS21,HS22,HS22V,HP DL380)。

在 Windows 2008 上运行测试应用程序可以在较小程度上证明该问题(更频繁,但峰值更小)。

我们如何才能修复这个问题或者下一步应该去哪里寻找呢?


示例中的实际代码:

void handle_receive_from(const boost::system::error_code& error,
    size_t bytes_recvd)
{
    if (!error)
    {
        ++m_receivedPackets;
        m_receivedBytes += bytes_recvd;
        m_last64TotalBytes += bytes_recvd;
        if ( ( m_receivedPackets & 0x3F ) == 0 )
        {
            printf( "Received %u bytes in %u packets. The average size of the last 64 packets was %u bytes, and the last byte received was %x.\n", 
                m_receivedBytes, m_receivedPackets, m_last64TotalBytes / 64, m_buffer[ bytes_recvd - 1 ] );
            m_last64TotalBytes = 0;
        }

        m_socket.async_receive_from(
            boost::asio::buffer(m_buffer, max_length), m_senderEndpoint,
            boost::bind(&receiver::handle_receive_from, this,
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred));
    }
    else
    {
        std::cerr << "An error occurred when performing an asyncronous read." << std::endl;
        m_socket.get_io_service().stop();
    }
}

答案1

“看起来正在进行某种延期清理工作,但我们不知道具体是什么。”

这可能是垃圾收集,但我不确定垃圾收集是否显示为特权时间。如果这是一个 .NET 应用程序,您可以查看.NET CLR Memory性能计数器(尤其是 Gen 2 很昂贵)。

最后猜测可能的问题似乎有点倒退。最好的办法是分析你的应用程序,看看它在此期间做了什么,看看应用程序做了什么调用。你可能只需使用进程监控观察系统调用。

答案2

我假设系统正在接收多播数据包。您可以尝试阻止它接收数据包,看看是否会出现同样的问题吗?

加入多播组但没有监听数据包会怎么样?

您说这种情况发生在不同的系统上,但实际的 NIC 硬件呢?在那些不同的系统上,情况可能相同。

更新:如果所有系统都使用 Broadcom NIC,则问题可能出在 NIC 上。具体来说,Microsoft 提供的 Broadcom 驱动程序很差劲;Broadcom 网站上的驱动程序要好得多。

答案3

您可以查看两件事:您的线程量以及导致您的 DPC(延迟过程调用)的原因。

线程量子很容易解决(可能是一个转移注意力的话题,但最好检查一下);

  1. 右键单击“我的电脑”
  2. 选择属性
  3. 选择“高级”选项卡
  4. 在“性能”下选择“设置...”
  5. 在新窗口中选择“高级”选项卡(现在我们已双重高级!)
  6. 在“处理器调度”下选择哪个?“程序”还是“后台服务”?

最有可能的是选择了“后台服务”,请尝试选择“程序”。这将减少中断之间的时间量,并允许在处理器上以相同的时间量运行更多线程。您会获得更多中断,但处理时间会减少。

延迟过程调用的诊断稍微有点困难;

正如 @wfaulk 所说,这通常表示驱动程序存在问题。有一个方便的工具叫做DPC 延迟检查器这将帮助您诊断这些问题。即使这种情况发生在多个硬件平台上,它们可能仍然共享一个驱动程序。运行 DPC Checker 并按照其网站上的说明进行操作。

三个后续问题:

  1. 您是否在使用组合网卡?它们使用 TCP/IP 堆栈相互通信,可能会导致严重的 DPC 问题。

  2. 您的 NIC 是否支持 TCP 卸载?它已启用吗?

  3. (完全是瞎猜)您的测试服务器是域的一部分吗?默认情况下,GPO 每 90 分钟刷新一次...

相关内容