前言:我們都知道,直接從內存讀寫數據要比從硬盤讀寫數據快得多,因此更希望所有數據的讀取和寫入都在內存中完成,然而內存是有限的,這樣就引出了物理內存與虛擬內存的概念。
物理內存就是系統硬件提供的內存大小,是真正的內存。相對於物理內存,在 Linux 下還有一個虛擬內存的概念,虛擬內存是為了滿足物理內存的不足而提出的策略,它是利用磁盤空間虛擬出的一塊邏輯內存。用作虛擬內存的磁盤空間被稱為交換空間(又稱 swap 空間)。
作為物理內存的擴展,Linux 會在物理內存不足時,使用交換分區的虛擬內存,更詳細地說,就是內核會將暫時不用的內存塊信息寫到交換空間,這樣一來,物理內存得到了釋放,這塊內存就可以用於其他目的,當需要用到原始的內容時,這些信息會被重新從交換空間讀入物理內存。
Linux 的內存管理采取的是分頁存取機制,為了保證物理內存能得到充分的利用,內核會在適當的時候將物理內存中不經常使用的數據塊自動交換到虛擬內存中,而將經常使用的信息保留到物理內存。
要深入了解 Linux 內存運行機制,需要知道下面提到的幾個方面:
- 首先,Linux 系統會不時地進行頁面交換操作,以保持盡可能多的空閑物理內存,即使並沒有什么事情需要內存,Linux 也會交換出暫時不用的內存頁面,因為這樣可以大大節省等待交換所需的時間。
- 其次,Linux 進行頁面交換是有條件的,不是所有頁面在不用時都交換到虛擬內存,Linux 內核根據“最近最經常使用”算法,僅僅將一些不經常使用的頁面文件交換到虛擬內存。
有時我們會看到這么一個現象,Linux 物理內存還有很多,但是交換空間也使用了很多,其實這並不奇怪。例如,一個占用很大內存的進程運行時,需要耗費很多內存資源,此時就會有一些不常用頁面文件被交換到虛擬內存中,但后來這個占用很多內存資源的進程結束並釋放了很多內存時,剛才被交換出去的頁面文件並不會自動交換進物理內存(除非有這個必要),那么此時系統物理內存就會空閑很多,同時交換空間也在被使用,就出現了剛才所說的現象了。
最后,交換空間的頁面在使用時會首先被交換到物理內存,如果此時沒有足夠的物理內存來容納這些頁面,它們又會被馬上交換出去,如此一來,虛擬內存中可能沒有足夠的空間來存儲這些交換頁面,最終會導致 Linux 出現假死機、服務異常等問題。Linux 雖然可以在一段時間內自行恢復,但是恢復后的系統己經基本不可用了。
因此,合理規划和設計 Linux 內存的使用是非常重要的,關於物理內存和交換空間的大小設置問題,取決於實際所用的硬盤大小,但大致遵循這樣一個基本原則:
-
- 如果內存較小(根據經驗,物理內存小於 4GB),一般設置 swap 分區大小為內存的 2 倍;
- 如果物理內存大於 4GB,而小於 16GB,可以設置 swap 分區大小等於物理內存;
- 如果內存大小在 16GB 以上,可以設置 swap 為 0,但並不建議這么做,因為設置一定大小的 swap 分區是有一定作用的。
建立swap分區的方式可以見http://c.biancheng.net/view/907.html
內存是linux中很重要的一塊,內存不足、內存泄漏、內存溢出也是在測試項目中經常會遇到的問題。
1. 物理內存和虛擬內存
物理內存指通過物理內存條而獲得的內存空間,稱為RAM。而虛擬內存則是指將硬盤的一塊區域划分來作為內存。內存主要作用是在計算機運行時為操作系統和各種程序提供臨時儲存。當物理內存不足時,可以用虛擬內存代替。虛擬內存的概念,是為了滿足物理內存不足的情況下,利用磁盤空間虛擬出的一塊邏輯內存,用作虛擬內存的磁盤空間被稱為交換空間(swap space)。vm.swappiness是Linux內核的一個參數,范圍是0~100。它表示實際內存和虛擬內存區域進行數據交換的傾向性大小,數值越大表示傾向性越大,即交換的頁面文件越多,反之亦然。一般默認值為60。可用'cat /proc/sys/vm/swappiness’查看。
Linux會在物理內存不足的時,使用交換分區的虛擬內存,也就是說,內核會將暫時不用的內存塊信息寫到交換空間,以釋放物理內存。Linux的內存管理采取的是分頁存取機制,為了保證物理內存能得到充分的利用,內核會在適當的時候將物理內存中不經常使用的數據塊自動交換到虛擬內存中,而將經常使用的信息保留到物理內存。swap si/so 交換區的換進換出。
所有的進程都需要內存,但是不是每個進程都需要一直將對象加載到內存中。基於這點,kernel通過將進程的部分或全部內存換出到磁盤上,來釋放物理內存,直到需要再次使用,然后再次讀到內存中。kernel采用分頁和交換進行內存管理。其中:
si:將分頁被重新讀取到物理內存。也稱作page-in
so:將內存的要交換的分頁寫到磁盤上。也稱作page-out
2. Buffer與Cache
buffer 和 cache都是通過使用物理內存的一部分,其中A buffer is something that has yet to be "written" to disk. A cache is something that has been "read" from the disk and stored for later use.
但是我們平常對系統資源進行監控時看到的buffer cache,其實都是cache,其中,buffer是buffer cache,cache是page cache,例如free命令中展示的結果:
Mem是物理內存統計,如上面顯示的,total表示物理內存總量是8006M,used表示總計分配給緩存(包括buffers和cached的)使用的數量,但其中可能部分緩存並未實際使用。used使用的內存有7253M,free未被分配的內存為752M,共享內存shared 一般系統不會用到,總是0。Buffer是系統分配但未被使用的buffer數量有183M,cache是系統分配但未被使用的cache數量有5153M,關系:total(8006M) = used(7253M) + free(752M),除去buffer和cache,真正使用的內存即-/+ buffers/cache中顯示的used的值,也就是1934M。即下面的關系:
(-buffers/cache) used內存數:1934M (指的第一部Mem行中的used–buffers– cached)
(+buffers/cache) free內存數: 6071M (指的第一部分Mem行中的free + buffers + cached)
所以-buffers/cache反映的是被程序實實在在吃掉的內存,而+buffers/cache反映的是可以挪用的內存總數。
3. Linux下的內存的監控方法
1)free命令查看內存
在linux下用free –help查看使用規則,詳見1.2節
參數:
-b 以Byte為單位顯示內存使用情況。
-k 以KB為單位顯示內存使用情況。
-m 以MB為單位顯示內存使用情況。
-o 不顯示緩沖區調節列。
-s<間隔秒數> 持續觀察內存使用狀況。
-t 顯示內存總和列。
-V 顯示版本信息。
2) vmstat命令查看內存
vmstat 1 【Virtual Meomory Statistics(虛擬內存統計)】命令查看內存使用情況:
其中
Procs(進程):
r: 運行隊列中進程數量(runnable),當這個值超過了CPU數目,就會出現CPU瓶頸了。這個也和top的負載有關系;
b: 表示阻塞的進程,等待IO的進程數量(blocked)
Memory(內存):
swpd: 使用虛擬內存大小,如果大於0,表示你的機器物理內存不足了,如果不是程序內存泄露的原因,那么你該升級內存了或者把耗內存的任務遷移到其他機器。;
free: 空閑的物理內存大小;
buff: 用作緩沖的內存大小,Linux/Unix系統是用來存儲,目錄里面有什么內容,權限等的緩存;
cache: 用作緩存的內存大小,直接用來記憶我們打開的文件,給文件做緩沖;
Swap:
si: 每秒從磁盤寫到內存的大小,如果這個值大於0,表示物理內存不夠用或者內存泄露了,要查找耗內存進程解決掉;
so: 每秒寫入磁盤的內存大小;
【內存夠用的時候,這兩個值都為0,若這兩個值長期大於0時,系統性能會受到影響,並且磁盤IO 和cpu資源都會被消耗】
bi: 塊設備每秒接收的塊數量,這里的塊設備是指系統上所有的磁盤和其他塊設備,默認塊大小是1024byte,我本機上沒什么IO操作,所以一直是0;
bo: 塊設備每秒發送的塊數量,例如我們讀取文件,bo就要大於0;
【bi和bo一般都要接近0,不然就是IO過於頻繁,需要調整】
system:
in: 每秒cpu中斷數,包括時間中斷。
cs: 每秒上下文切換數。(content switch)
這兩個值越大,說明cpu里面的sys會越大
CPU(以百分比表示):
us: 用戶進程執行時間(user time);
sy: 系統進程執行時間(system time);
id: 空閑時間(包括IO等待時間),中央處理器的空閑時間【越接近0表示cpu越繁忙】 。以百分比表示;
wa: 進程等待IO完成而使cpu處於空閑狀態的時間片比例
這個命令中應該主要看參數: r,b,si,so
3) sar命令
sar –R和sar –r可以用來監控內存問題
kbmemfree:這個值和free命令中的free值基本一致,所以它不包括buffer和cache的空間.
kbmemused:這個值和free命令中的used值基本一致,所以它包括buffer和cache的空間.
%memused:這個值是kbmemused和內存總量(不包括swap)的一個百分比.
kbbuffers和kbcached:這兩個值就是free命令中的buffer和cache.
kbcommit:保證當前系統所需要的內存,即為了確保不溢出而需要的內存(RAM+swap).
%commit:這個值是kbcommit與內存總量(包括swap)的一個百分比
4. 內存泄漏和內存溢出
內存溢出 out of memory,是指程序在申請內存時,沒有足夠的內存空間供其使用,出現out of memory;比如申請了一個integer,但給它存了long才能存下的數,那就是內存溢出。
內存泄露 memory leak,是指程序在申請內存后,無法釋放已申請的內存空間,一次內存泄露危害可以忽略,但內存泄露堆積后果很嚴重,無論多少內存,遲早會被占光。內存泄漏可以從如下方法中進行判斷:
1)jvisualvm中查看堆的變化,如下左圖是正常的,右圖就是發生了內存泄漏的:
2)用 jstat -gcutil PID,觀察Old這個參數,如果每次執行完FULLGC之后Old區的值一次比一次升高,就可以判斷為發生了內存泄漏、