UDP接收线程占用太多CPU资源
UDP recvfrom thread use too much CPU resources
我正在写一个Windows 7 visual c++服务器应用程序,它应该以3.6 MB/s的速度接收UDP数据报。我有一个主线程,其中recvfrom()接收数据。套接字是非阻塞套接字,具有64kB的接收缓冲区。如果在套接字上没有接收到数据,线程执行睡眠(1)。
我的问题是线程占用了我的双核处理器的近50%,我不知道如何减少它。Wireshark只使用了20%,所以我的主要目标是达到类似的百分比。
你有什么想法吗?
比起轮询,您可以使用类似选择的方法来等待数据到达套接字或客户端决定关闭:
首先使你的套接字非阻塞:
u_long nonBlocking = 0;
WSAEventSelect(sock, NULL, 0);
ioctlsocket(sock, FIONBIO, &nonBlocking);
然后使用WSAWaitForMultipleEvents等待,直到数据到达或您想要取消接收:
int32_t MyRecv(THandle sock, WSAEVENT* recvCancelEvt,
uint8_t* buffer, uint32_t bufferBytes)
{
int32_t bytesReceived;
WSAEVENT evt;
DWORD ret;
HANDLE handles[2];
event = WSACreateEvent();
if (NULL == evt) {
return -1;
}
if (0 != WSAEventSelect(handle->iSocket, evt, FD_READ|FD_CLOSE)) {
WSACloseEvent(evt);
return -1;
}
bytesReceived = recv(sock, (char*)buffer, bufferBytes, 0);
if (SOCKET_ERROR==received && WSAEWOULDBLOCK==WSAGetLastError()) {
handles[0] = evt;
handles[1] = *recvCancelEvt;
ret = WSAWaitForMultipleEvents(2, handles, FALSE, INFINITE, FALSE);
if (WAIT_OBJECT_0 == ret) {
bytesReceived = recv(handle->iSocket, (char*)buffer, bufferBytes, 0);
}
}
WSACloseEvent(evt);
return bytesReceived;
}
客户端代码在recvCancelEvt
上调用WSASetEvent
,如果它想取消一个recv
虽然基于选择或阻塞套接字的解决方案是正确的方法,但您在100%运行一个核心的原因是由于Sleep的行为:-
查看WinAPI sleep():
这个函数使线程放弃剩余的时间的值在一段时间内变得不可运行dwMilliseconds。系统时钟以恒定的速率"滴答"。dwMilliseconds小于系统时钟的分辨率
因此,如果您正在轮询,您要么需要使用更长的睡眠时间(可能是20Ms,这通常比Windows的滴答率大一点),要么使用更精确的多媒体计时器。
我建议使用boost::asio::io_service。我们收到大约200MB/s的UDP多播流量,同时最大限度地利用现代CPU。这包括一个完整的可靠性协议和应用程序的数据调度。性能分析的瓶颈是处理,而不是boost::asio接收。代码
看起来大多数时候对recvfrom的调用都不返回数据。睡1毫秒并不多。您应该考虑增加睡眠时间(便宜,但不是最好的解决方案),或者,更好的解决方案是考虑使用事件驱动的方法。使用select()
或Windows API阻塞,直到套接字信号或其他一些您感兴趣的事件发生,然后调用recvfrom
。您可能需要为此重新设计程序的主循环。
- 在没有太多条件句的情况下,我如何避免被零除
- 错误:字符数组的初始值设定项太多
- 对象实例化调用构造函数的次数太多
- Levenshtein 两个文件的距离花费了太多时间
- 我有三个 getline,但是一旦编译,输入就太多了
- 将使用太多的纹理插值器 - 带旋转的着色器
- C/C++:socket() 创建在循环中失败,打开的文件太多
- 使用Visual Studio在虚幻引擎中创建一个新的类c ++给了我太多的错误
- C++:数组<>初始值设定项太多
- GLib-ERROR:为GWakeup创建管道:打开的文件太多
- C++,从文件读取到结构,然后读取到向量(结构被推入向量太多次,而不仅仅是一次)
- 我会导致太多内存泄漏,以至于我的计算机无响应吗?
- ZeroMq:打开的文件太多.在同一对象上连续增长的fd使用数
- 读取串行命令花费太多时间
- 为什么 Boost unordered_map 在第一次插入时需要太多时间?
- BRK(0) 花费的时间是否太多?
- Valgrind 声称内存释放中的自由空间太多
- 如果分支太多C++
- 压缩太多文件
- UDP接收线程占用太多CPU资源