首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >UDP服务器占用高CPU

UDP服务器占用高CPU
EN

Stack Overflow用户
提问于 2022-01-18 19:56:03
回答 1查看 191关注 0票数 0

我在我的UDP服务器实现中观察到较高的CPU使用率,它运行一个无限循环,期望每毫秒有15个1.5KB的数据包。如下所示:

代码语言:javascript
运行
复制
struct RecvContext
{

    enum { BufferSize = 1600 };

    RecvContext() 
    { 
        senderSockAddrLen = sizeof(sockaddr_storage);
        memset(&overlapped, 0, sizeof(OVERLAPPED));
        overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
        memset(&sendersSockAddr, 0, sizeof(sockaddr_storage));
        buffer.clear();
        buffer.resize(BufferSize);
        wsabuf.buf = (char*)buffer.data();
        wsabuf.len = ULONG(buffer.size());
    }

    void CloseEventHandle()
    {
        if (overlapped.hEvent != INVALID_HANDLE_VALUE)
        {
            CloseHandle(overlapped.hEvent);
            overlapped.hEvent = INVALID_HANDLE_VALUE;
        }
    }

    OVERLAPPED overlapped;
    int senderSockAddrLen;
    sockaddr_storage sendersSockAddr;
    std::vector<uint8_t> buffer;
    WSABUF wsabuf;
};

void Receive()
{
    DWORD flags = 0, bytesRecv = 0;

    SOCKET sockHandle =...;

    while (//stopping condition//)
    {

        std::shared_ptr<RecvContext> _recvContext = std::make_shared<IO::RecvContext>();

        if (SOCKET_ERROR == WSARecvFrom(sockHandle, &_recvContext->wsabuf, 1, nullptr, &flags, (sockaddr*)&_recvContext->sendersSockAddr,
            (LPINT)&_recvContext->senderSockAddrLen, &_recvContext->overlapped, nullptr))
        {
            if (WSAGetLastError() != WSA_IO_PENDING)
            {
                //error
            }
            else
            {
                if (WSA_WAIT_FAILED == WSAWaitForMultipleEvents(1, &_recvContext->overlapped.hEvent, FALSE, INFINITE, FALSE))
                {
                    //error
                }

                if (!WSAGetOverlappedResult(sockHandle, &_recvContext->overlapped, &bytesRecv, FALSE, &flags))
                {
                    //error
                }
            }
        }

        _recvContext->CloseEventHandle();
        // async task to process _recvContext->buffer
    }
}

此udp服务器的cpu消耗非常高,即使在未处理数据包时也是如此。如何在这里提高cpu消耗?

EN

回答 1

Stack Overflow用户

发布于 2022-01-18 20:10:42

你选择了最低效的机制组合。

如果只准备发送一个操作,然后等待操作完成,为什么要使用重叠I/O呢?

  1. 为什么要使用一个事件,这是Windows拥有的最慢的通知方案。

  1. 为什么每次只发送一个操作?您强迫实现将数据报存储在自己的缓冲区中,然后将它们复制到您的.

中。

  1. 为什么要在等待它完成之前发布接收操作,而不是在上一个操作完成之后呢?

  1. 为什么每次创建一个新的接收上下文,而不是重用现有的缓冲区、事件等等?

使用IOCP。Windows事件是非常缓慢和沉重的。

发布了大量的操作。您希望操作系统能够将数据报正确地放在缓冲区中,而不必分配另一个缓冲区来复制数据。

重复使用缓冲区,并从连续池分配所有接收缓冲区,而不是在整个进程内存中分割它们。用于缓冲区的内存必须固定,并且您希望最小化所需的固定量。

一旦他们完成了重新部署的操作。不要处理它们,然后重新发布。没有理由推迟手术的开始。如果您遵循所有其他建议,您可能会忽略这一点,因为您无论如何都没有一个“备用”缓冲区可供发布。

或者,您可能可以通过在阻塞接收操作上旋转的线程而逃脱。只需确保您的代码有一个尽可能紧凑的循环,在分派另一个线程来处理刚刚填充了接收操作的缓冲区后,一旦它返回,就会提交一个不同的(已经分配的)缓冲区。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70761659

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档