CPU使用率高的ussleep在Cent OS 6.3上
CPU high usage of the usleep on Cent OS 6.3
我在cent os 5.3和cent os 6.3上编译了下面的代码:
#include <pthread.h>
#include <list>
#include <unistd.h>
#include <iostream>
using namespace std;
pthread_mutex_t _mutex;
pthread_spinlock_t spinlock;
list<int *> _task_list;
void * run(void*);
int main()
{
int worker_num = 3;
pthread_t pids[worker_num];
pthread_mutex_init(&_mutex, NULL);
for (int worker_i = 0; worker_i < worker_num; ++worker_i)
{
pthread_create(&(pids[worker_i]), NULL, run, NULL);
}
sleep(14);
}
void *run(void * args)
{
int *recved_info;
long long start;
while (true)
{
pthread_mutex_lock(&_mutex);
if (_task_list.empty())
{
recved_info = 0;
}
else
{
recved_info = _task_list.front();
_task_list.pop_front();
}
pthread_mutex_unlock(&_mutex);
if (recved_info == 0)
{
int f = usleep(1);
continue;
}
}
}
在5.3上运行时,你甚至找不到最上面的进程,cpu使用率大约是0%。但在os 6.3上,在4核cpu上6个线程的情况下,它大约是20%。
所以我用time和stace检查a.o out,结果是:5.3:
real 0m14.003s
user 0m0.001s
sys 0m0.001s
6.3:
real 0m14.002s
user 0m1.484s
sys 0m1.160s
strace :
5.3:
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
91.71 0.002997 0 14965 nanosleep
8.29 0.000271 271 1 execve
0.00 0.000000 0 5 read
0.00 0.000000 0 10 4 open
0.00 0.000000 0 6 close
0.00 0.000000 0 4 4 stat
0.00 0.000000 0 6 fstat
0.00 0.000000 0 22 mmap
0.00 0.000000 0 13 mprotect
0.00 0.000000 0 1 munmap
0.00 0.000000 0 3 brk
0.00 0.000000 0 3 rt_sigaction
0.00 0.000000 0 3 rt_sigprocmask
0.00 0.000000 0 1 1 access
0.00 0.000000 0 3 clone
0.00 0.000000 0 1 uname
0.00 0.000000 0 1 getrlimit
0.00 0.000000 0 1 arch_prctl
0.00 0.000000 0 38 4 futex
0.00 0.000000 0 1 set_tid_address
0.00 0.000000 0 4 set_robust_list
------ ----------- ----------- --------- --------- ----------------
100.00 0.003268 15092 13 total
6.3:
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
99.99 1.372813 36 38219 nanosleep
0.01 0.000104 0 409 43 futex
0.00 0.000000 0 5 read
0.00 0.000000 0 6 open
0.00 0.000000 0 6 close
0.00 0.000000 0 6 fstat
0.00 0.000000 0 22 mmap
0.00 0.000000 0 15 mprotect
0.00 0.000000 0 1 munmap
0.00 0.000000 0 3 brk
0.00 0.000000 0 3 rt_sigaction
0.00 0.000000 0 3 rt_sigprocmask
0.00 0.000000 0 7 7 access
0.00 0.000000 0 3 clone
0.00 0.000000 0 1 execve
0.00 0.000000 0 1 getrlimit
0.00 0.000000 0 1 arch_prctl
0.00 0.000000 0 1 set_tid_address
0.00 0.000000 0 4 set_robust_list
------ ----------- ----------- --------- --------- ----------------
100.00 1.372917 38716 50 total
时间和距离的结果不是相同的测试,所以数据略有不同。但我认为它可以显示一些东西。
我检查内核配置CONFIG_HIGH_RES_TIMERS, CONFIG_HPET和CONFIG_HZ:
5.3:
$ cat /boot/config-`uname -r` |grep CONFIG_HIGH_RES_TIMERS
$ cat /boot/config-`uname -r` |grep CONFIG_HPET
CONFIG_HPET_TIMER=y
CONFIG_HPET_EMULATE_RTC=y
CONFIG_HPET=y
# CONFIG_HPET_RTC_IRQ is not set
# CONFIG_HPET_MMAP is not set
$ cat /boot/config-`uname -r` |grep CONFIG_HZ
# CONFIG_HZ_100 is not set
# CONFIG_HZ_250 is not set
CONFIG_HZ_1000=y
CONFIG_HZ=1000
6.3:
$ cat /boot/config-`uname -r` |grep CONFIG_HIGH_RES_TIMERS
CONFIG_HIGH_RES_TIMERS=y
$ cat /boot/config-`uname -r` |grep CONFIG_HPET
CONFIG_HPET_TIMER=y
CONFIG_HPET_EMULATE_RTC=y
CONFIG_HPET=y
CONFIG_HPET_MMAP=y
$ cat /boot/config-`uname -r` |grep CONFIG_HZ
# CONFIG_HZ_100 is not set
# CONFIG_HZ_250 is not set
# CONFIG_HZ_300 is not set
CONFIG_HZ_1000=y
CONFIG_HZ=1000
实际上,我也在ARM和xubuntu13.04-amd64-desktop的arch上尝试了这些代码,与os 6.3相同。
那么我能做些什么来找出不同CPU使用的原因呢?
它有什么与内核配置?
你是对的,这与内核配置有关。usleep(1)
将尝试睡眠一微秒。在高分辨率计时器出现之前,睡眠时间不可能少于1秒(在你的情况下,HZ=1000,所以1秒== 1毫秒)。
在没有这些高分辨率计时器的CentOS 5.3上,您将在1ms到2ms之间休眠[1]。在有这些计时器的CentOS 6.3上,你的睡眠时间接近一微秒。这就是为什么你在这个平台上使用更多的cpu:你只是轮询你的任务列表500-1000倍。
如果您将代码更改为usleep(1000)
, CentOS 5.3将表现相同。CentOS 6.3的cpu时间将会减少,并且与在CentOS 5.3上运行的程序大致相同
在Linux手册中有完整的讨论:run man 7 time
.
请注意,您的代码应该使用条件变量,而不是以特定的时间间隔轮询任务列表。这是一种更高效、更干净的做事方式。
另外,你的main应该真正地加入线程,而不是仅仅睡14秒。
[1]有一个例外。如果您的应用程序在实时调度策略(SCHED_FIFO或SCHED_RR)下运行,那么它将忙等待而不是休眠,以接近正确的睡眠量。但是默认情况下你需要root权限
- "ostream &os"有什么用?
- libprotobuf 检查在 Mac OS 上执行程序时失败
- C++读取用户输入而不按回车键(Mac OS X),与Turbo Pascal中的读取键相同
- 如何在 MAC OS c/c++ 中阻止 USB 存储设备
- 编译 Boost 时在 OS X 上的"ld:未知选项:-soname"
- 在 c++ 中检查 Windows OS 服务器版本
- OS X: ld: 找不到 -lstdc++ 的库
- Python os.system() 返回错误值
- Mac os x app bundle 在下载并运行时崩溃,但在终端或更改 Info.plist 时运行良好
- const 如何防止写入特定内存 [Clang, Mac OS]
- 旧C++代码中的目录查找导致 OS X Catalina 10.15 中的目录错误
- 如何在 Mac OS 上安装 boost-mpi 及其对 clang 的依赖关系?
- 在 Mac OS 中将 QT 与 CMAKE 集成
- Homebrew OS X OpenCV - 在另一台Mac上运行时寻找dylib
- 使用C/C++访问OS X密钥链
- 谷歌测试编译错误 Os X:函数式转换从"int"到"internal::FloatingEq2Matcher"的模糊转换<float>
- 从我的2d数组中的一列返回的字符串值被压缩为一个字符串(在Mac os上打开Windows txt文件)
- 如何在Cent OS 6.5上构建freetype
- CPU使用率高的ussleep在Cent OS 6.3上
- 错误:在 Linux (Cent OS) 中,“__extension__”之前应存在非限定 ID