19 | 案例篇:为什么系统的Swap变高了(上)
生活随笔
收集整理的這篇文章主要介紹了
19 | 案例篇:为什么系统的Swap变高了(上)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
上一節,我通過一個斐波那契數列的案例,帶你學習了內存泄漏的分析。如果在程序中直接或間接地分配了動態內存,你一定要記得釋放掉它們,否則就會導致內存泄漏,嚴重時甚至會耗盡系統內存。不過,反過來講,當發生了內存泄漏時,或者運行了大內存的應用程序,導致系統的內存資源緊張時,系統又會如何應對呢?在內存基礎篇我們已經學過,這其實會導致兩種可能結果,內存回收和 OOM 殺死進程。我們先來看后一個可能結果,內存資源緊張導致的 OOM(Out Of Memory),相對容易理解,指的是系統殺死占用大量內存的進程,釋放這些內存,再分配給其他更需要的進程。這一點我們前面詳細講過,這里就不再重復了。接下來再看第一個可能的結果,內存回收,也就是系統釋放掉可以回收的內存,比如我前面講過的緩存和緩沖區,就屬于可回收內存。它們在內存管理中,通常被叫做文件頁(File-backed Page)。大部分文件頁,都可以直接回收,以后有需要時,再從磁盤重新讀取就可以了。而那些被應用程序修改過,并且暫時還沒寫入磁盤的數據(也就是臟頁),就得先寫入磁盤,然后才能進行內存釋放。這些臟頁,一般可以通過兩種方式寫入磁盤。
- 可以在應用程序中,通過系統調用 fsync ,把臟頁同步到磁盤中;
- 也可以交給系統,由內核線程 pdflush 負責這些臟頁的刷新。
文件頁
除了緩存和緩沖區,通過內存映射獲取的文件映射頁,也是一種常見的文件頁。它也可以被釋放掉,下次再訪問的時候,從文件重新讀取。匿名頁
除了文件頁外,還有沒有其他的內存可以回收呢?比如,應用程序動態分配的堆內存,也就是我們在內存管理中說到的匿名頁(Anonymous Page),是不是也可以回收呢?我想,你肯定會說,它們很可能還要再次被訪問啊,當然不能直接回收了。非常正確,這些內存自然不能直接釋放。但是,如果這些內存在分配后很少被訪問,似乎也是一種資源浪費。是不是可以把它們暫時先存在磁盤里,釋放內存給其他更需要的進程?其實,這正是 Linux 的 Swap 機制。Swap 把這些不常訪問的內存先寫到磁盤中,然后釋放這些內存,給其他更需要的進程使用。再次訪問這些內存時,重新從磁盤讀入內存就可以了。在前幾節的案例中,我們已經分別學過緩存和 OOM 的原理和分析。那 Swap 又是怎么工作的呢?因為內容比較多,接下來,我將用兩節課的內容,帶你探索 Swap 的工作原理,以及 Swap 升高后的分析方法。今天我們先來看看,Swap 究竟是怎么工作的。Swap 原理
前面提到,Swap 說白了就是把一塊磁盤空間或者一個本地文件(以下講解以磁盤為例),當成內存來使用。它包括換出和換入兩個過程。- 所謂換出,就是把進程暫時不用的內存數據存儲到磁盤中,并釋放這些數據占用的內存。
- 而換入,則是在進程再次訪問這些內存的時候,把它們從磁盤讀到內存中來。
- 剩余內存小于頁最小閾值,說明進程可用內存都耗盡了,只有內核才可以分配內存。
- 剩余內存落在頁最小閾值和頁低閾值中間,說明內存壓力比較大,剩余內存不多了。這時 kswapd0 會執行內存回收,直到剩余內存大于高閾值為止。
- 剩余內存落在頁低閾值和頁高閾值中間,說明內存有一定壓力,但還可以滿足新內存請求。
- 剩余內存大于頁高閾值,說明剩余內存比較多,沒有內存壓力。
NUMA 與 Swap
很多情況下,你明明發現了 Swap 升高,可是在分析系統的內存使用時,卻很可能發現,系統剩余內存還多著呢。為什么剩余內存很多的情況下,也會發生 Swap 呢?看到上面的標題,你應該已經想到了,這正是處理器的 NUMA (Non-Uniform Memory Access)架構導致的。關于 NUMA,我在 CPU 模塊中曾簡單提到過。在 NUMA 架構下,多個處理器被劃分到不同 Node 上,且每個 Node 都擁有自己的本地內存空間。而同一個 Node 內部的內存空間,實際上又可以進一步分為不同的內存域(Zone),比如直接內存訪問區(DMA)、普通內存區(NORMAL)、偽內存區(MOVABLE)等,如下圖所示:先不用特別關注這些內存域的具體含義,我們只要會查看閾值的配置,以及緩存、匿名頁的實際使用情況就夠了。既然 NUMA 架構下的每個 Node 都有自己的本地內存空間,那么,在分析內存的使用時,我們也應該針對每個 Node 單獨分析。你可以通過 numactl 命令,來查看處理器在 Node 的分布情況,以及每個 Node 的內存使用情況。比如,下面就是一個 numactl 輸出的示例:$ numactl --hardware available: 1 nodes (0) node 0 cpus: 0 1 node 0 size: 7977 MB node 0 free: 4416 MB ...這個界面顯示,我的系統中只有一個 Node,也就是 Node 0 ,而且編號為 0 和 1 的兩個 CPU, 都位于 Node 0 上。另外,Node 0 的內存大小為 7977 MB,剩余內存為 4416 MB。了解了 NUNA 的架構和 NUMA 內存的查看方法后,你可能就要問了這跟 Swap 有什么關系呢?實際上,前面提到的三個內存閾值(頁最小閾值、頁低閾值和頁高閾值),都可以通過內存域在 proc 文件系統中的接口 /proc/zoneinfo 來查看。比如,下面就是一個 /proc/zoneinfo 文件的內容示例:$ cat /proc/zoneinfo ... Node 0, zone Normalpages free 227894min 14896low 18620high 22344 ...nr_free_pages 227894nr_zone_inactive_anon 11082nr_zone_active_anon 14024nr_zone_inactive_file 539024nr_zone_active_file 923986 ...這個輸出中有大量指標,我來解釋一下比較重要的幾個。- pages 處的 min、low、high,就是上面提到的三個內存閾值,而 free 是剩余內存頁數,它跟后面的 nr_free_pages 相同。
- nr_zone_active_anon 和 nr_zone_inactive_anon,分別是活躍和非活躍的匿名頁數。
- nr_zone_active_file 和 nr_zone_inactive_file,分別是活躍和非活躍的文件頁數。
- 默認的 0 ,也就是剛剛提到的模式,表示既可以從其他 Node 尋找空閑內存,也可以從本地回收內存。
- 1、2、4 都表示只回收本地內存,2 表示可以回寫臟數據回收內存,4 表示可以用 Swap 方式回收內存。
swappiness
到這里,我們就可以理解內存回收的機制了。這些回收的內存既包括了文件頁,又包括了匿名頁。- 對文件頁的回收,當然就是直接回收緩存,或者把臟頁寫回磁盤后再回收。
- 而對匿名頁的回收,其實就是通過 Swap 機制,把它們寫入磁盤后再釋放內存。
小結
在內存資源緊張時,Linux 通過直接內存回收和定期掃描的方式,來釋放文件頁和匿名頁,以便把內存分配給更需要的進程使用。- 文件頁的回收比較容易理解,直接清空,或者把臟數據寫回磁盤后再釋放。
- 而對匿名頁的回收,需要通過 Swap 換出到磁盤中,下次訪問時,再從磁盤換入到內存中。
總結
以上是生活随笔為你收集整理的19 | 案例篇:为什么系统的Swap变高了(上)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 18 | 案例篇:内存泄漏了,我该如何定
- 下一篇: RealARM开发板 TFTP下载内核和