我了解命令報告的各種類型的 cpu 使用情況top
(6.5%us
、17.2%sy
、0.0%ni
等...),但為什麼每個進程的總 %CPU 相加不等於任何值Cpu(s)
?例如,下面的 java 進程消耗了 77.5% CPU,但Cpu(s)
表示 76.0% 仍然空閒。為什麼是這樣?這是在單核心系統上。
top - 05:53:27 up 32 min, 2 users, load average: 0.16, 0.29, 0.34
Tasks: 71 total, 1 running, 70 sleeping, 0 stopped, 0 zombie
Cpu(s): 6.5%us, 17.2%sy, 0.0%ni, 76.0%id, 0.0%wa, 0.0%hi, 0.3%si, 0.0%st
Mem: 1758616k total, 643432k used, 1115184k free, 12224k buffers
Swap: 917500k total, 0k used, 917500k free, 304608k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1307 tomcat 20 0 683m 287m 9528 S 77.5 16.8 10:54.99 java
1571 ec2-user 20 0 2592 1096 872 R 1.0 0.1 0:08.61 top
1 root 20 0 2892 1364 1168 S 0.0 0.1 0:00.28 init
2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd
編輯:原來這是雙核心系統。以下是top
命令啟動時按 1 後更新的輸出:
top - 06:10:21 up 49 min, 2 users, load average: 0.28, 0.37, 0.34
Tasks: 71 total, 1 running, 70 sleeping, 0 stopped, 0 zombie
Cpu0 : 9.9%us, 19.7%sy, 0.0%ni, 69.0%id, 0.0%wa, 0.0%hi, 1.4%si, 0.0%st
Cpu1 : 5.0%us, 10.0%sy, 0.0%ni, 85.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 1758616k total, 677548k used, 1081068k free, 13296k buffers
Swap: 917500k total, 0k used, 917500k free, 305732k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1307 tomcat 20 0 683m 318m 9528 S 68.0 18.6 17:23.53 java
1 root 20 0 2892 1364 1168 S 0.0 0.1 0:00.28 init
2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd
3 root 20 0 0 0 0 S 0.0 0.0 0:00.91 ksoftirqd/0
4 root RT 0 0 0 0 S 0.0 0.0 0:00.00 migration/0
答案1
您正在比較的這兩個資訊不匹配,原因很簡單,因為它們是從不同的文件收集的。也就是說,雖然 top 在同一終端機中顯示訊息,但它們不是從同一來源收集的。
我只是在上面運行了一個 strace (以批次模式運行)。這是顯示系統範圍 CPU 資訊的地方。
16:04:04.081092 open("/proc/stat", O_RDONLY) = 6 <0.000022>
16:04:04.081154 lstat("/proc", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0 <0.000015>
16:04:04.081211 lstat("/proc/stat", {st_mode=S_IFREG|0444, st_size=0, ...}) = 0 <0.000013>
16:04:04.081267 fstat(6, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0 <0.000013>
16:04:04.081334 fstat(6, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0 <0.000013>
16:04:04.081385 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f699ace2000 <0.000016>
16:04:04.081440 lseek(6, 0, SEEK_SET) = 0 <0.000013>
16:04:04.081494 read(6, "cpu 302573 6910 83103 10092403 "..., 1024) = 1024 <0.000070>
16:04:04.081656 write(1, "%Cpu(s): 2.9 us, 0.8 sy, 0.1 "..., 80) = 80 <0.000034>
16:04:04.081763 write(1, "KiB Mem: 8048484 total, 41402"..., 73) = 73 <0.000035>
16:04:04.081858 write(1, "KiB Swap: 8060924 total, "..., 72) = 72 <0.000034>
16:04:04.081940 write(1, "\n", 1) = 1 <0.000026>
現在,如果您看到/proc/stat
,它顯示了系統的所有 CPU。 top 也知道這一點,因為在開啟 /proc/stat 之前,它會開啟 sys 檔案系統。
16:04:03.367339 open("/sys/devices/system/cpu/online", O_RDONLY|O_CLOEXEC) = 3 <0.000027>
16:04:03.367408 read(3, "0-7\n", 8192) = 4 <0.000019>
16:04:03.367464 close(3) = 0 <0.000015>
現在,當涉及到收集單一進程資訊時,它會從檔案中獲取該/proc/pid/statm
資訊/proc/pid/stat
。 (將 pid 替換為實際的 pid)。
正如您所看到的,/proc/stat
系統範圍的資訊是全部CPU 和 pid 的各個 proc 檔案是其特定的 pid-only 資訊。
所以,他們不會匹配。
答案2
採樣(衡量 CPU 使用情況的方法top
)可能會出現錯誤。
最好的解釋方式是這樣的:想像一家工廠每小時只生產一輛汽車。假設您決定對工廠生產汽車的速度進行採樣。您在 5:59 開始採樣,並在 7:01 停止採樣。您會看到生產了兩輛汽車,一輛在 6:00 生產,另一輛在 7:00 生產。您採樣了 62 分鐘,生產了 2 輛汽車。因此,您可以計算出該工廠的汽車生產量約為其額定產能的 200%。
此外,您無法將top
值相互比較,因為top
它不會為您提供一組單一系統狀態的測量值,而是一組獨立的測量值,每個測量值都受其自己的一組條件的影響。
例如,可以使用與每個進程值完全不同的機制來計算每個 CPU 值。每個 CPU 的值可以呈指數衰減,而每個行程的值可以是兩個總數之間的差異。因此它們可以反映同一類型事物的測量結果,但使用完全不同的方法。