Linux效能調優命令之free

塵世風發表於2021-05-22

功能說明

free 命令顯示系統使用和空閒的記憶體情況,包括實體記憶體、互動區記憶體(swap)和核心緩衝區記憶體。共享記憶體將被忽略

語法

free [引數]

引數

  • -b : 以Byte為單位顯示記憶體使用情況。
  • -k :  以KB為單位顯示記憶體使用情況。
  • -m :  以MB為單位顯示記憶體使用情況。
  • -h: 以適於人類可讀方式顯示記憶體資訊。-h與其他命令最大不同是-h選項會在數字後面加上適於人類可讀的單位
  • -g : 以GB為單位顯示記憶體使用情況。
  • -o :  不顯示緩衝區調節列。
  • -s: <間隔秒數>  持續觀察記憶體使用狀況。
  • -t :  顯示記憶體總和列。
  • -V :  顯示版本資訊。

image
如果加上 -h 選項,輸出的結果會友好很多:
image
有時我們需要持續的觀察記憶體的狀況,此時可以使用 -s 選項並指定間隔的秒數:

$ free -h -s 3

image

上面的命令每隔 3 秒輸出一次記憶體的使用情況,直到你按下 ctrl + c。

由於 free 命令本身比較簡單,所以本文的重點會放在如何通過 free 命令瞭解系統當前的記憶體使用狀況。

基本概念

下面先解釋一下輸出的內容:

第一列

  • Mem 行(第二行)是記憶體的使用情況。
  • Swap 行(第三行)是交換空間的使用情況。

第一行

  • total 列顯示系統總的可用實體記憶體和交換空間大小。
  • used 列顯示已經被使用的實體記憶體和交換空間。
  • free 列顯示還有多少實體記憶體和交換空間可用使用。
  • shared 列顯示被共享使用的實體記憶體大小。
  • buff/cache 列顯示被 buffer 和 cache 使用的實體記憶體大小。
  • available 列顯示還可以被應用程式使用的實體記憶體大小。

buff/cache:

從字面上和語義來看,buffer名為緩衝,cache名為快取。我們知道各種硬體存在製作工藝上的差別,所以當兩種硬體需要互動的時候,肯定會存在速度上的差異,而且只有互動雙方都完成才可以各自處理別的其他事務。假如現在有兩個需要互動的裝置A和B,A裝置用來互動的介面速率為1000M/s,B裝置用來互動的介面速率為500M/s,那他們彼此訪問的時候都會出現以下兩種情況:(以A來說)

一.A從B取一個1000M的檔案結果需要2s,本來需要1s就可以完成的工作,卻還需要額外等待1s,B裝置把剩餘的500M找出來,這等待B取出剩下500M的空閒時間內(1s)其他的事務還幹不了

二.A給B一個1000M的檔案結果也需要2s,本來需要也就1s就可以完成的工作,卻由於B,1s內只能拿500M,剩下的500M還得等下一個1sB來取,這等待下1s的時間還做不了其他事務。

那有什麼方法既可以讓A在‘取’或‘給’B的時候既能完成目標任務又不浪費那1s空閒等待時間去處理其他事務呢?我們知道產生這種結果主要是因為B跟不上A的節奏,但即使這樣A也得必須等B處理完本次事務才能幹其他活(單核cpu來說),除非你有三頭六臂。那有小夥伴可能會問了,能不能在A和B之間加一層區域比如說ab,讓ab既能跟上A的頻率也會照顧B的感受,沒錯我們確實可以這樣設計來磨合介面速率上的差異,你可以這樣想象,在區域ab提供了兩個互動介面一個是a介面另一個是b介面,a介面的速率接近A,b介面的速率最少等於B,然後我們把ab的a和A相連,ab的b和B相連,ab就像一座橋把A和B連結起來,並告知A和B通過他都能轉發給對方,檔案可以暫時儲存,最終拓撲大概如下:

image
現在我們再來看上述兩種情況:

對於第一種情況A要B:當A從B取一個1000M的檔案,他把需求告訴了ab,接下來ab通過b和B進行檔案傳送,由於B本身的速率,傳送第一次ab並沒有什麼卵用,對A來說不僅浪費了時間還浪費了感情,ab這傢伙很快感受到了A的不滿,所以在第二次傳送的時候,ab揹著B偷偷快取了一個一模一樣的檔案,而且只要從B取東西,ab都會快取一個拷貝下來放在自己的大本營,如果下次A或者其他C來取B的東西,ab直接就給A或C一個貨真價實的贗品,然後把它通過a介面給了A或C,由於a的速率相對接近A的介面速率,所以A覺得不錯為他省了時間,最終和ab的a成了好基友,說白了此時的ab提供的就是一種快取能力,即cache,絕對的走私!因為C取的是A執行的結果。所以在這種工作模式下,怎麼取得的東西是最新的也是我們需要考慮的,一般就是清cache。例如cpu讀取記憶體資料,硬碟一般都提供一個記憶體作為快取來增加系統的讀取效能

對於第二種情況A給B:當A發給B一個1000M的檔案,因為A知道通過ab的a介面就可以轉交給B,而且通過a介面要比通過B介面傳送檔案需要等待的時間更短,所以1000M通過a介面給了ab ,站在A檢視上他認為已經把1000M的檔案給了B,但對於ab並不立即交給B,而是先快取下來,除非B執行sync命令,即使B馬上要,但由於b的介面速率最少大於B介面速率,所以也不會存在漏洞時間,但最終的結果是A節約了時間就可以幹其他的事務,說白了就是推卸責任,哈哈而ab此時提供的就是一種緩衝的能力,即buffer,它存在的目的適用於當速度快的往速度慢的輸出東西。例如記憶體的資料要寫到磁碟,cpu暫存器裡的資料寫到記憶體。

看了上面這個例子,那我們現在看一下在計算機領域,在處理磁碟IO讀寫的時候,cpu,memory,disk基於這種模型給出的一個例項。我們先來一幅圖:(我從別家當來的,我覺得,看N篇文件 不如瞄此一圖)
image
page cache:檔案系統層級的快取,從磁碟裡讀取的內容是儲存到這裡,這樣程式讀取磁碟內容就會非常快,比如使用grep和find等命令查詢內容和檔案時,第一次會慢很多,再次執行就快好多倍,幾乎是瞬間。但如上所說,如果對檔案的更新不關心,就沒必要清cache,否則如果要實施同步,必須要把記憶體空間中的cache clean下

buffer cache:磁碟等塊裝置的緩衝,記憶體的這一部分是要寫入到磁碟裡的。這種情況需要注意,位於記憶體buffer中的資料不是即時寫入磁碟,而是系統空閒或者buffer達到一定大小統一寫到磁碟中,所以斷電易失,為了防止資料丟失所以我們最好正常關機或者多執行幾次sync命令,讓位於buffer上的資料立刻寫到磁碟裡。

free 與 available

在 free 命令的輸出中,有一個 free 列,同時還有一個 available 列。這二者到底有何區別?
free 是真正尚未被使用的實體記憶體數量。至於 available 就比較有意思了,它是從應用程式的角度看到的可用記憶體數量。Linux 核心為了提升磁碟操作的效能,會消耗一部分記憶體去快取磁碟資料,就是我們介紹的 buffer 和 cache。所以對於核心來說,buffer 和 cache 都屬於已經被使用的記憶體。當應用程式需要記憶體時,如果沒有足夠的 free 記憶體可以用,核心就會從 buffer 和 cache 中回收記憶體來滿足應用程式的請求。所以從應用程式的角度來說,available = free + buffer + cache。請注意,這只是一個很理想的計算方式,實際中的資料往往有較大的誤差。

交換空間(swap space)

swap space 是磁碟上的一塊區域,可以是一個分割槽,也可以是一個檔案。所以具體的實現可以是 swap 分割槽也可以是 swap 檔案。當系統實體記憶體吃緊時,Linux 會將記憶體中不常訪問的資料儲存到 swap 上,這樣系統就有更多的實體記憶體為各個程式服務,而當系統需要訪問 swap 上儲存的內容時,再將 swap 上的資料載入到記憶體中,這就是常說的換出和換入。交換空間可以在一定程度上緩解記憶體不足的情況,但是它需要讀寫磁碟資料,所以效能不是很高。

現在的機器一般都不太缺記憶體,如果系統預設還是使用了 swap 是不是會拖累系統的效能?理論上是的,但實際上可能性並不是很大。並且核心提供了一個叫做 swappiness 的引數,用於配置需要將記憶體中不常用的資料移到 swap 中去的緊迫程度。這個引數的取值範圍是 0~100,0 告訴核心儘可能的不要將記憶體資料移到 swap 中,也即只有在迫不得已的情況下才這麼做,而 100 告訴核心只要有可能,儘量的將記憶體中不常訪問的資料移到 swap 中。在 ubuntu 系統中,swappiness 的預設值是 60。如果我們覺著記憶體充足,可以在 /etc/sysctl.conf 檔案中設定 swappiness:

vm.swappiness=10

如果系統的記憶體不足,則需要根據實體記憶體的大小來設定交換空間的大小。具體的策略網上有很豐富的資料,這裡筆者不再贅述。

/proc/meminfo 檔案

其實 free 命令中的資訊都來自於 /proc/meminfo 檔案。/proc/meminfo 檔案包含了更多更原始的資訊,只是看起來不太直觀:
image

有興趣的同學可以直接檢視這個檔案。

總結

free 命令是一個既簡單又複雜的命令。簡單是因為這個命令的引數少,輸出結果清晰。說它複雜則是因為它背後是比較晦澀的作業系統中的概念,如果不清楚這些概念,即便看了 free 命令的輸出也 get 不到多少有價值的資訊。

相關文章