首先,top
命令是没有计算load的平均值的,top
命令只不过是在不停的从/proc/loadavg
文件来读取load的平均值.(strace
显示top
命令会打开/proc/loadavg
并且会定期从中读取load的平均值信息).当使用man proc
的时候,会有如下说明:
/proc/loadavg
该文件的前三个属性,分别表示在1分钟,5分钟和15分钟内,任务队列中进程的平均个数.
任务需保证:
- 进程状态是R
- 进程在等待磁盘IO,状态是D
这3个数字也可以通过一些其他的命令来获取,比如
uptime
等命令.而第四个属性包括两个数字,以/
分开.第一个数字是当前内核调度实体的数量(进程,线程);这个数字会低于或者等于CPU的个数.而/
后面的数字表示在当前系统中存在的内核调度实体个数.第5个属性则是操作系统最常创建进程的PID.
所以说,load average
只是表示运行队列中运行任务的多少.并且,开发者从top
中只能看到1分钟,5分钟和15分钟的平均值.如果开发者运行cat /proc/loadavg
那么将会看到文件中的其它属性值.
前面描述的load average
的描述是来自于man
的,但是其实经过测试,貌似并非十分准确.我写了一个简单的java程序来创建256个线程,代码如下:
import java.lang.Thread;
import java.lang.Runnable;
public class test {
public static void main(String[] args) {
int n = 256;
for (int i = 0;inew Thread(new Runnable() {
@Override
public void run() {
while(true){
}
}
}).start();
}
}
}
当实际执行的过程中,再执行了cat /proc/loadavg
的时候,返回的结果如下:
71.41 18.25 6.28 264/928 26598
而这台服务器本身只是虚拟机,如下为cat /proc/cpuinfo
的值:
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 45
model name : Intel(R) Xeon(R) CPU E5-2430 0 @ 2.20GHz
stepping : 7
cpu MHz : 2199.885
cache size : 15360 KB
physical id : 0
siblings : 1
core id : 0
cpu cores : 1
apicid : 0
initial apicid : 0
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat clflush mmx fxsr sse sse2 ht syscall nx lm up rep_good unfair_spinlock pni ssse3 cx16 sse4_1 sse4_2 popcnt aes hypervisor lahf_lm
bogomips : 4399.77
clflush size : 64
cache_alignment : 64
address sizes : 46 bits physical, 48 bits virtual
本身只有单CPU,单核,而实际上,264这个数字很明显是高于这个值的.所以之前对于/proc/loadavg
的第四个属性描述不是很正确.这个属于load average
的一个描述错误.
在proc的manual page中,对于loadavg第四个属性的
/
左边的数值描述是错误的.该值表示的是当前的执行调度实体,所以就预测其值应该不高于当前CPU的个数.这和其实现并不相符,该值其实表示的是当前的runnable
线程.
Q:现在来了个问题,当load平均值是7的时候,有4个超线程的CPU内核,是不是意味着CPU的利用率在7/8?
A:答案是否定的,load平均值为7只是表示在当前的执行队列中有7个运行进程.
Q:那么为什么其显示为50%id?这种情况怎么会出现一般时间的CPU空闲?
A:因为load average
并不意味着CPU的占比.开发者的线程只是使用了50%的CPU,而另外50%的CPU在做其他事情罢了.