1mega大小的大阵列导致CPU过高
Big array of size 1mega caused high CPU?
我有一个多线程服务器应用程序。该应用程序从套接字接收数据,然后处理这些数据,如拆包、添加到数据队列等,功能如下。此函数经常被调用。有一个select语句,如果它发现有数据,它将调用此函数来接收):
//the main function used to receive
//file data from clients
void service(void){
while(1){
....
struct timeval timeout;
timeout.tv_sec = 3;
...
ret = select(maxFd+1, &read_set, NULL, NULL, &timeout);
if (ret > 0){
//get socket from SocketsMap
//if fd in SocketsMap and its being set
//then receive data from the socket
receive_data(fd);
}
}
}
void receive_data(int fd){
const int ONE_MEGA = 1024 * 1024;
//char *buffer = new char[ONE_MEGA]; consumes much less CPU
char buffer[ONE_MEGA]; // cause high CPU
int readn = recv(fd, buffer, ONE_MEGA, 0);
//handle the data
}
我发现上面的方法消耗了太多的CPU——通常是80%到90%,但如果我从堆中创建缓冲区,那么CPU只有14%。为什么?
[更新]
添加了更多代码
[更新2]
最重要的是,我还编写了另一个简单的数据接收服务器和客户端。服务器只是从套接字接收数据,然后丢弃它。两种类型的空间分配工作原理几乎相同,CPU使用率没有太大差异。在出现问题的多线程服务器应用程序中,我甚至将进程堆栈大小重置为30M,使用数组仍然会出现问题,但从堆中分配解决了问题。我不知道为什么。
关于"sizeof(buffer)",感谢您指出这一点,但我100%确信这不是问题所在,因为在我的应用程序中,我不使用sizeof(buffer),而是使用ONE_MEGA(1024*1024)。
顺便说一句,还有一件事要提,尽管我不确定它是否有用用较小的数组(如"char buffer[1024];)替换数组也会显著降低cpu使用率。
[更新3]
所有插座都处于非阻塞模式。
我刚刚写了这个:
#include <iostream>
#include <cstdio>
using namespace std;
static __inline__ unsigned long long rdtsc(void)
{
unsigned hi, lo;
__asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
}
const int M = 1024*1024;
void bigstack()
{
FILE *f = fopen("test.txt", "r");
unsigned long long time;
char buffer[M];
time = rdtsc();
fread(buffer, M, 1, f);
time = rdtsc() - time;
fclose(f);
cout << "bs: Time = " << time / 1000 << endl;
}
void bigheap()
{
FILE *f = fopen("test.txt", "r");
unsigned long long time;
char *buffer = new char[M];
time = rdtsc();
fread(buffer, M, 1, f);
time = rdtsc() - time;
delete [] buffer;
fclose(f);
cout << "bh: Time = " << time / 1000 << endl;
}
int main()
{
for(int i = 0; i < 10; i++)
{
bigstack();
bigheap();
}
}
输出是这样的:
bs: Time = 8434
bh: Time = 7242
bs: Time = 1094
bh: Time = 2060
bs: Time = 842
bh: Time = 830
bs: Time = 785
bh: Time = 781
bs: Time = 782
bh: Time = 804
bs: Time = 782
bh: Time = 778
bs: Time = 792
bh: Time = 809
bs: Time = 785
bh: Time = 786
bs: Time = 782
bh: Time = 829
bs: Time = 786
bh: Time = 781
换句话说,从堆的堆栈中进行分配绝对没有区别。一开始的少量"缓慢"与"预热缓存"有关。
我非常确信,您的代码在两者之间表现不同的原因是其他原因——也许是simonc所说的:sizeof buffer
是问题所在?
如果所有东西都相等,那么内存就是内存,缓冲区是在堆上还是在堆栈上都无关紧要。
但很明显,并非所有事物都是平等的。我怀疑堆栈上1M缓冲区的分配与分配给OTHER线程的堆栈空间发生了INTERFERES/OVERLAPS。也就是说,增加堆栈需要重新定位当前线程的堆栈,或者重新定位其他线程的堆栈。这需要时间。当从堆中进行分配时,或者如果堆栈分配足够小而不会干扰,则不需要此时间,就像1K示例一样。
假设您使用的是Posix兼容的线程实现,请查看
pthread_create
pthread_attr_getstack
pthread_attr_setstack
用于在线程创建时给具有1M缓冲区的线程更多的堆栈空间。
-Jeff
您忽略了recv
的返回值。这不好。部分读取是生活中的一个事实,如果你通过这么大的缓冲区,很可能会这样。当您开始处理缓冲区中不包含有效数据的部分时,可能会发生意想不到的事情。
最常用的协议的最大帧大小是64kB。甚至有可能(尽管不太可能)系统中的某些东西只使用缓冲区大小的最低16位,顺便说一下,您已经将其设置为零。这将导致recv
立即返回而不执行任何操作,从而导致无休止的循环和高CPU使用率。
当然,对于动态分配的缓冲区,这一切都不应该有任何不同,但如果也使用了sizeof (buffer)
,并且最终堆用户代码一次只读取指针大小的块,那么情况可能会有所不同。
- 一段时间后 CPU 使用率高
- 高CPU使用率,在API桌面复制中获取帧之间具有不同的超时间隔
- GetDC ReleaseDC 在特定上下文中的高 CPU 使用率
- 共创建实例消耗高 CPU
- DX9 桌面窗口管理器高 CPU
- Qnetworkreply,QnetworkAccessManager- https下载文件 - 高CPU使用情况
- 使用boost :: pool时使用高CPU
- Loop Wregex始终返回false和高CPU使用率约50%
- 当CPU使用率高时,OpenCV会堆积内存吗
- 使用轮询系统调用等待 fds 时 CPU 使用率高
- 使用MQTT deamon时CPU利用率高.
- 平铺使所有值1过高
- 使用OpenCV从多个网络摄像头捕获多个静止图像时带宽过高
- 1mega大小的大阵列导致CPU过高
- CPU使用率高的常见原因是什么
- CPU使用率高的Win32应用程序
- CPU使用率高的ussleep在Cent OS 6.3上
- STM32 ADC读数过高
- 绘制gl场景时CPU使用率高;来源
- 从/dev/ ttyacm0读取时cpu负载高