首先,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;i<n;i++) {
new 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在做其他事情罷了.