在排查操作系统升级后应用性能降低过程中,发现同硬件平台下2.6.32内核版本usleep函数产生的开销远大于2.6.18内核上的。
软硬件环境如下
主机A |
主机B |
CPU Intel E5-2630 24核2.6GHz 内存 DDR3 64GB |
|
RHEL-6.4 |
RHEL-5.7 |
测试代码:
<span style="font-size:18px;">#include<unistd.h> int main() { for(i = 0; i < 1000; i++) { usleep(10); } } </span>
下表是精度比较结果:
usleep间隔 |
usleep次数 |
主机A耗时 |
主机B耗时 |
精度 |
usleep(1) |
99999 |
5.56s |
145s |
定时精度差26倍 |
usleep(1000) |
1000 |
1.057s |
2.001s |
定时精度差2倍 |
usleep(10000) |
1000 |
10.061s |
11.144s |
定时精度差10.7% |
usleep(50000) |
1000 |
50.064s |
51.054 |
定时精度差1.9% |
为什么在2.6.32内核上usleep精度要高很多?
根据http://elinux.org/High_Resolution_Timers的介绍,linux在2.6.21内核上采用了High Resolution Timers算法,极大的提高了时间精度。
那么High Resolution Timers的开销如何呢?
从下表是使用time命令统计的usleep开销,可以看到在主机B(2.6.18内核)上usleep基本不消耗CPU时间,当然它的精度很差。而主机B(2.6.32内核)上usleep有明显的CPU开销,usleep(1)时通过top命令看到占用4~6%的CPU。
column |
usleep |
real(s) |
user(s) |
sys(s) |
sum(s) |
主机A |
1 |
0.058 |
0 |
0.004 |
0.004 |
10 |
0.061 |
0 |
0.004 |
0.004 |
|
100 |
0.119 |
0.002 |
0.004 |
0.006 |
|
1000 |
1.052 |
0.001 |
0.003 |
0.004 |
|
10000 |
10.056 |
0.002 |
0.003 |
0.005 |
|
100000 |
100.052 |
0.002 |
0.004 |
0.006 |
|
主机B |
1 |
1 |
0 |
0 |
0 |
10 |
1.001 |
0 |
0 |
0 |
|
100 |
1.001 |
0 |
0 |
0 |
|
1000 |
2.001 |
0 |
0 |
0 |
|
10000 |
11.001 |
0 |
0 |
0 |
|
100000 |
101.03 |
0 |
0 |
0 |
从对不同usleep间隔绘制的CPU消耗曲线可以看出,CPU占用与usleep间隔关系不大。
由于High Resolution Timers算法是内核底层的时间机制,select、epool_wait这些替代的时间算法都会受到影响。
建议:
对于使用usleep等时间切换函数来实现任务空闲切换功能的应用,可以采用等待信号量唤醒的方法进行休眠,减少CPU开销,如schedule、pause、pthread_cond_wait等。
参考资料:
http://bbs.csdn.net/topics/380254421
http://elinux.org/High_Resolution_Timers
来自 littlefang-镇关西拳打鲁智深 的CSDN博客,转载请注明原文:http://blog.csdn.net/littlefang/article/details/44680975