我编译下面的代码分5.3和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%左右。 但在6.3版本中,在4核心cpu上有6个线程,这个数字约为20%。
所以我经常检查一下 ,结果是这样的:
在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
时间和strace结果是不一样的testing,所以数据是有点不同。 但我认为它可以显示一些东西。
我检查内核configurationCONFIG_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上的代码,与cent os 6.3相同。
那么我能做些什么来找出不同CPU使用率的原因呢?
它有什么与内核configuration?
你是对的,它与内核配置有关。 睡觉usleep(1)
将尝试睡眠一微秒。 在高分辨率定时器之前,不可能睡得比不上jiffy(在你的情况下HZ = 1000,所以1 jiffy == 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手册中有一个完整的讨论:运行man 7 time
。
请注意,您的代码应该使用条件变量,而不是以特定的时间间隔轮询您的任务列表。 这是一个更有效和干净的方式来做你正在做的事情。
此外,你的主要应该真的加入线程,而不是只睡14秒。
[1]有一个例外。 如果您的应用程序正在实时调度策略(SCHED_FIFO或SCHED_RR)下运行,则它将忙于等待,而不是睡觉以睡眠接近正确的数量。 但是默认情况下你需要root权限