W2K3E 上系统 CPU 使用率的无法解释的周期性驼峰

Mik*_*eyB 7 networking windows-server-2003 performance-tuning

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

我们将其简化为一个简单的应用程序,仅做以下事情:

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

测试应用程序本身是Boost ASIO 多播接收器示例的略微修改版本,因此应该不会出现太多错误。下面的实际代码(!)...

每隔一段时间在负载下运行这个程序时,这个进程的 CPU 会随着内核代码中发生的所有处理而加速:

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

从图中可以看出,当负载峰值达到时,所有处理时间都发生在内核代码中。花费的时间主要用于延迟过程调用(最多 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

Kyl*_*ndt 1

“看起来正在进行某种推迟的清理工作,但我们不知道会发生什么。”

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

最后猜测可能的问题似乎有点倒退。最好的办法是分析您的应用程序,看看它在此期间正在做什么,以了解应用程序正在进行哪些调用。您也许可以只使用进程监视器来监视系统调用。