我在我的UDP服务器实现中观察到较高的CPU使用率,它运行一个无限循环,期望每毫秒有15个1.5KB的数据包。如下所示:
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消耗?
发布于 2022-01-18 20:10:42
你选择了最低效的机制组合。
如果只准备发送一个操作,然后等待操作完成,为什么要使用重叠I/O呢?
中。
使用IOCP。Windows事件是非常缓慢和沉重的。
发布了大量的操作。您希望操作系统能够将数据报正确地放在缓冲区中,而不必分配另一个缓冲区来复制数据。
重复使用缓冲区,并从连续池分配所有接收缓冲区,而不是在整个进程内存中分割它们。用于缓冲区的内存必须固定,并且您希望最小化所需的固定量。
一旦他们完成了重新部署的操作。不要处理它们,然后重新发布。没有理由推迟手术的开始。如果您遵循所有其他建议,您可能会忽略这一点,因为您无论如何都没有一个“备用”缓冲区可供发布。
或者,您可能可以通过在阻塞接收操作上旋转的线程而逃脱。只需确保您的代码有一个尽可能紧凑的循环,在分派另一个线程来处理刚刚填充了接收操作的缓冲区后,一旦它返回,就会提交一个不同的(已经分配的)缓冲区。
https://stackoverflow.com/questions/70761659
复制相似问题