你一定用過 htop,但你有看懂每個欄位嗎?

Larry Lu
Starbugs Weekly 星巴哥技術專欄
11 min readMay 16, 2021

--

身為一個工程師,不管你寫的是前端、後端、全端還是什麼端,一定多少用過 htop,就算真的沒用過也會聽同事說過。htop 是一個 process manager,他可以讓你看到執行中的 process、系統資源的使用量,也可以讓你輕鬆 kill 掉任何一個 process,總之,你想得到的功能統統都有~

雖然大家都說 htop 很好用,但許多人打開 htop 也只看得懂 CPU、Mem、PID、Command 這些簡單的欄位,對於 Load average、NI、State、SHR 就沒那麼熟悉

不過 htop 都幫你列出來了,看不懂好像又有點可惜對吧!所以這篇文章要跟大家鉅細彌遺的介紹 htop 每個欄位的意義,也許哪天有需要時就能派上用場呢!

CPU

首先來說說最重要的 CPU,在 htop 最上方會列出各 CPU 的使用率,值得注意的是這邊顯示的是 CPU 的邏輯核心數,譬如說你的電腦有四核心八執行緒,意思是同時可以執行八個 thread,那這邊就會顯示八個 CPU 哦~

另外不知道有沒有人發現這個使用率的 bar 包含了紅色綠色,有時甚至還會有藍色,那其實是有意義的哦:

  • 紅色 代表的是 kernel thread 佔用的 CPU,像是系統需要自動做 process scheduling、memory management 等等,是整個系統中最重要、優先權也最高的任務
  • 綠色 代表的是 normal priority thread,排程的優先權比 kernel thread 低一些,一般來說使用者執行的程式如果沒有特別調優先權的話,都會歸在這一類
  • 藍色 的話就是 low priority thread,因為優先權比較低,分配到的 CPU 自然也比較少,適合「我 ok,你先跑」那類比較無關緊要的 process,如果 CPU 已經被操到快不行了,或是 memory 真的不夠用了,第一個殺掉的也是這類 process

Memory & Swap

緊接在 CPU 下面的是 memory 跟 swap 的使用量,memory 這邊應該大家都看得懂,值得一提的是他的顏色也是有意義的:

  • 綠色 指的是被 process 佔用的記憶體,譬如說你開的瀏覽器、VSCode、終端機等等程式,還有正在執行的 htop 都算是這一類
  • 藍色 則是 buffer pages,他是用來儲存一些 metadata。譬如說當你第一次執行 ls -l 時系統會去硬碟撈看這個資料夾有哪些檔案、每個檔案的權限等等,然後幫你存在 buffer pages,當你短時間內再執行 ls -l 時就不用再進入硬碟(因為硬碟很慢),直接從 buffer 拿即可
  • 橘色cache pages 跟 buffer 很像,只不過 buffer 存的是 metadata,而 cache 存的是檔案內容。像你第一次下 cat index.js 時就會把內容讀取到 cache pages,如果你 cat 之後發現程式碼太長,決定先看前十行就好了,那再下 head -n 10 index.js 就會從 cache pages 直接讀取

這也代表說記憶體使用量並非越低越好,畢竟閒在那邊也沒啥用,不如讓系統把閒置的部分拿去當 buffer 跟 cache,讀取時能不碰硬碟就不碰硬碟,才可以讓程式執行得更快

所以千萬不要相信什麼「記憶體清理大師」可以幫你提升效能,說真的沒變慢就不錯了XD,隨便把 buffer 跟 cache 都清掉了只會加重系統負擔。記憶體管理就交給系統來,十之八九都可以管理得還不錯

而 swap 的部分雖然上圖完全沒用到,但還是解釋一下:swap 的機制跟剛剛提到的 cache & buffer 正好相反,萬一你實在開了太多程式,而且每個程式都跟 chrome 一樣狂吃猛吃,導致 memory 快要不夠了

那系統就會把記憶體裡面一些東西 swap 到硬碟上,等真的需要那些東西時再從硬碟拿回來。雖然這樣做看似有更多記憶體可以用,但代價就是程式速度會慢上許多,因為硬碟實在是太慢了

順帶一提 swap 的發音是「司哇ㄆㄜ」,不要再唸成「司位ㄆㄜ」了~

Load Average

接著來看看螢幕右上方那堆神奇的數字

首先 Tasks 欄位的 488, 1994 thr; 3 running 代表的是目前總共有 488 的 process、1994 個 thread,其中 3 個 thread 正在執行(這數字最大就是你的邏輯核心數)

Load Average(LA) 是用來判斷斷目前系統有多繁忙,三個數字代表的是系統在最近 1分鐘、5分鐘、15 分鐘內,平均有多少個 thread 需要 CPU

以上圖來說,近一分鐘內平均有 5.9 個 thread 需要使用 CPU 進行運算,但無奈我只有 4 個邏輯核心,所以 CPU 是忙到翻過來(因為我正在編譯 Rust 執行檔XD),而最近十五分鐘的 LA 是 3.49,其實也算是高了

一般來說電腦完全沒在用時 LA 會低於 1,而平常在上網、聽音樂、做簡報則是會介於 1 到 2 之間

所以如果覺得自己寫的程式跑很慢,不妨先看看 LA 確認瓶頸是不是在 CPU,如果 LA 很低但程式卻慢得誇張,那很可能程式並沒有善用多核心,或是瓶頸卡在硬碟跟網路 IO;如果 LA 已經很高了但還是覺得太慢,那就只能改善演算法、或是換更快的 CPU 了

PID/USER

上面講完之後來看看下面這一大塊,這部分每個 row 都是一個 process,而 PID 就是每個 process 的 ID

那知道 PID 之後可以幹嘛呢?其實他的用途挺多的,譬如說你可以用 kill -KILL <pid> 來殺掉某個 process;或是使用 kill -STOP 來暫停 process 再用 kill -CONT 讓他繼續執行(這超好用 👍,但好像很多人都不知道)

而 USER 欄位沒什麼好解釋的XD,就是把這個 process 跑起來的人。不管程式是誰寫的,只要是我把他跑起來,USER 那欄就會顯示我的名字

PRI & NI

接下來的 Priority 跟 Nice 兩個都是跟優先權有關的指標,注意數字越小表示優先權越高,也就可以分配到越多 CPU 時間

其中 PRI 是由系統幫你決定的,無法自行修改,像上圖 mdbulkimport 的 PRI 值是 17,而 ping 8.8.8.8 則是 24,代表系統認為 mdbulkimport 比 ping 來得重要

註:mdbulkimport 是 mac spotlight 功能的一部分

而 nice 值的部分預設是 0,可以用 renice -n 19 -p <pid> 調整到最低優先權 19,想要調高的話最高也可以調到 -20

雖然 nice 值可以隨自己高興調高調低,但系統不見得都會聽你的。有的系統比較友善會願意參考你設的 nice 值,但也有一些只看 PRI 系統根本不在乎 nice,你設你的我排我的XD,所以不要太期待提高優先權可以為效能帶來多大的變化,想要提升效能還是乖乖把程式寫好比較重要~

VIRT/RES/SHR

這三個數字都是跟記憶體有關的,分別代表 Virtual memory、Resident 跟 Shared memory

Virtual memory 的概念比較複雜一點,基本上你可以把他想成 process 可以存取到的 memory 總和。譬如說 head -n index.js 內部運作的方式是先把 index.js 打開,然後讀取前十行

雖然他只讀取前十行,但 head process 已經把檔案打開了,他其實有權限 access 到整個檔案的內容(只是它沒有這麼做),所以 virtual memory 會把整個檔案的大小算進去

而 Resident 正好相反,他指的是物理上你到底佔用了多少記憶體。以同樣的例子來說,若你只讀取前十行,那系統就只把前十行從硬碟讀進記憶體,RES 也就只算那十行

因此在 htop 裡面 RES 一定會小於 VIRT(如下圖),而且通常是遠小於,因為 VIRT 會把一堆哩哩叩叩的東西都算進去,所以就算看到 VIRT 很肥也完全不用擔心

而 Shared memory 的話顧名思義就是可以跟別人分享的 memory,像程式執行時很常會用的 glibc,或是在讀取 read-only 檔案時,這些東西都只需要讀進記憶體一次就可以了,所以就會被算進 SHR 裡面

雖說能跟其他 process 共用記憶體是好事,但這種事也強求不來,所以一般我都只看 RES,很少在管 SHR 是多少

State

接著來看這小小一個 S,代表的是 process 的 state,比較常見的有以下幾個

  • R: 意思是 process 正在跑或是在 running queue 裡等待 CPU 排程

如果你的程式長時間處於 R 狀態但還是跑很慢,代表可能是演算法太慢了,或是 CPU 實在太忙一直把你丟在 queue 裡面,可以再透過 CPU% 來確認是哪個問題

  • S: 目前正在睡覺,有事做才會醒來

通常定時執行的、要使用者互動的程式如 ping 跟 VSCode 很常會處於 S 狀態(上圖),畢竟 ping 一秒只送一個封包,但現今的 CPU 一秒可以跑十億個 cycle,所以 CPU 當然是送出封包後就馬上把你踢到旁邊去睡覺,等一秒後你睡醒了再回來

VSCode 的話是因為你總不可能一秒打十億個字吧,所以沒事做的時候他會馬上被 CPU 踢出去,等你打字了他再被叫回來動一下,然後馬上又被踢出去(怎麼感覺有點慘XD)

  • D: 這個也是在睡覺,只不過等待的一定是 IO,譬如說讀取檔案、寫入資料庫等等

如果你的 process 長時間處於 D 狀態,代表 IO 所佔的時間比較多,三不五時就被 CPU 踢出去睡覺。因此想改善效能也要從 IO 著手,譬如用 redis 做快取或是換 SSD 等等,若只是單純更換程式語言或是升級 CPU 可能沒什麼效果

CPU%/MEM%

CPU% 意思是你在這段時間平均用了幾顆 CPU,因為 htop 預設 3 秒更新一次,假如前 1.5 秒你用了一顆,後 1.5 都沒用,那平均就是 50%;如果你這三秒用好用滿四個核心,那就是漂亮的 400%(上圖 Rust 編譯器的其中一個 process 就有用到 331%)

因為 CPU% 是很短期的數據,所以當你突然覺得電腦當當的快不行時,直接看 CPU% 就可以知道是誰在作怪,然後看是要用 signal 把他暫停還是乾脆直接殺掉

MEM% 也很類似,就是使用記憶體的比例,要注意的是他是用 RES 來做計算,所以如果電腦配有 4GB 的記憶體、某個 process 的 RES 是 1GB,那他就是用掉實體記憶體的 25%

Time+

最後要來說說 Time+,這個時間很有意思,他代表的並不是程式從啟動到現在總共經過了多久,而是這個程式總共佔用了多少 CPU Time

譬如說上圖我在編譯 Rust 時,雖然我才剛跑十秒而已,但 CPU Time 已經有 28 秒,代表說這個 process 在十秒內平均使用了 2.8 顆 CPU,也就是平均的 CPU% 是 280% 左右

相反的如果像 ping 8.8.8.8 這種幾乎不需要 CPU 運算的 process(就只是把封包送出去而已),那即便跑了十多分鐘,佔用的 CPU Time 也不過 12 秒而已,平均起來的 CPU% 大概是 2% 左右

因此如果想知道長期而言哪個程式最佔 CPU 的話,就看 Time+ 的數值;如果是想看短期、目前正在暴衝的程式,那就是看先前提到的 CPU%

總結

今天介紹了怎麼用 htop 看系統的負載狀態各種記憶體使用量、以及長短期的 CPU 使用率,看到這我想大家都累了,一下子資訊量太大說不定也忘得差不多了XD

但也沒關係,看完腦袋中有個概念就好了,先把文章收藏起來,哪天發現又看不太懂 htop 時,再回來當技術文件翻一下也可以哦~

延伸閱讀

--

--

Larry Lu
Starbugs Weekly 星巴哥技術專欄

我是 Larry 盧承億,傳說中的 0.1 倍工程師。我熱愛技術、喜歡與人分享,專長是 JS 跟 Go,平常會寫寫技術文章還有參加各種技術活動,歡迎大家來找我聊聊~