點選上方 "程式員小樂"關注公衆号, 星标或置頂一起成長
每天淩晨00點00分, 第一時間與你相約
每日英文
There shing road difficult to heart, the right state of mind can make your life more comfortable.
有心無難事,有誠路定通,正确的心态能讓你的人生更坦然舒心。
每日掏心話
不要因為沖動而說一些過激的話,沒有人願意拿熱情換冷漠,拿體貼換傷害。
來自:潇湘隐者 | 責編:樂樂
連結:cnblogs.com/kerrycode/p/9568854.html
程式員小樂(ID:study_tech)第 661 次推文 圖檔來自網絡
往日回顧:Spring Security 簡單教程以及實作完全前後端分離
正文
在Linux中,有很多指令或工具檢視記憶體使用情況,今天我們來看看如何檢視程序消耗、占用的記憶體情況,Linux的記憶體管理和相關概念要比Windows複雜一些。在此之前,我們需要了解一下Linux系統下面有關記憶體的專用名詞和專業術語概念:
實體記憶體和虛拟記憶體
實體記憶體:就是系統硬體提供的記憶體大小,是真正的記憶體,一般叫做記憶體條。也叫随機存取存儲器(random access memory,RAM)又稱作“随機存儲器”,是與CPU直接交換資料的内部存儲器,也叫主存(記憶體)。
虛拟記憶體:相對于實體記憶體,在Linux下還有一個虛拟記憶體的概念,虛拟記憶體就是為了滿足實體記憶體的不足而提出的政策,它是利用磁盤空間虛拟出的一塊邏輯記憶體,用作虛拟記憶體的磁盤空間被稱為交換空間(Swap Space)。Linux會在實體記憶體不足時,使用虛拟記憶體,核心會把暫時不用的記憶體塊資訊寫到虛拟記憶體,這樣實體記憶體就得到了釋放,這塊兒記憶體就可以用于其他目的,而需要用到這些内容的時候,這些資訊就會被重新從虛拟記憶體讀入實體記憶體。
Linux的buffers與cached
在Linux中經常發現空閑的記憶體很少,似乎所有的記憶體都被消耗殆盡了,表面上看是記憶體不夠用了,很多新手看到記憶體被“消耗殆盡”非常緊張,其實這個是因為Linux系統将空閑的記憶體用來做磁盤檔案資料的緩存。這個導緻你的系統看起來處于記憶體非常緊急的狀況。但是實際上不是這樣。這個差別于Windows的記憶體管理。Linux會利用空閑的記憶體來做cached & buffers。
buffers是指用來給塊裝置做的緩沖大小(塊裝置的讀寫緩沖區),它隻記錄檔案系統的metadata以及 tracking in-flight pages.
Buffers are associated with a specific block device, and cover caching of filesystem metadata as well as tracking in-flight pages. The cache only contains parked file data. That is, the buffers remember what’s in directories, what file permissions are, and keep track of what memory is being written from or read to for a particular block device. The cache only contains the contents of the files themselves.
cached是作為page cache的記憶體, 檔案系統的cache。你讀寫檔案的時候,Linux核心為了提高讀寫性能與速度,會将檔案在記憶體中進行緩存,這部分記憶體就是Cache Memory(緩存記憶體)。即使你的程式運作結束後,Cache Memory也不會自動釋放。這就會導緻你在Linux系統中程式頻繁讀寫檔案後,你會發現可用實體記憶體會很少。其實這緩存記憶體(Cache Memory)在你需要使用記憶體的時候會自動釋放,是以你不必擔心沒有記憶體可用
Cached is the size of the page cache. Buffers is the size of in-memory block I/O buffers. Cached matters; Buffers is largely irrelevant.
Cached is the size of the Linux page cache, minus the memory in the swap cache, which is represented by SwapCached (thus the total page cache size is Cached + SwapCached). Linux performs all file I/O through the page cache. Writes are implemented as simply marking as dirty the corresponding pages in the page cache; the flusher threads then periodically write back to disk any dirty pages. Reads are implemented by returning the data from the page cache; if the data is not yet in the cache, it is first populated. On a modern Linux system, Cached can easily be several gigabytes. It will shrink only in response to memory pressure. The system will purge the page cache along with swapping data out to disk to make available more memory as needed.
Buffers are in-memory block I/O buffers. They are relatively short-lived. Prior to Linux kernel version 2.4, Linux had separate page and buffer caches. Since 2.4, the page and buffer cache are unified and Buffers is raw disk blocks not represented in the page cache—i.e., not file data. The Buffers metric is thus of minimal importance. On most systems, Buffers is often only tens of megabytes.
Linux共享記憶體
共享記憶體是程序間通信中最簡單的方式之一。共享記憶體允許兩個或更多程序通路同一塊記憶體,就如同 malloc() 函數向不同程序傳回了指向同一個實體記憶體區域的指針。當一個程序改變了這塊位址中的内容的時候,其它程序都會察覺到這個。其實所謂共享記憶體,就是多個程序間共同地使用同一段實體記憶體空間,它是通過将同一段實體記憶體映射到不同程序的虛拟空間來實作的。由于映射到不同程序的虛拟空間中,不同程序可以直接使用,不需要像消息隊列那樣進行複制,是以共享記憶體的效率很高。共享記憶體可以通過mmap()映射普通檔案機制來實作,也可以System V共享記憶體機制來實作,System V是通過映射特殊檔案系統shm中的檔案實作程序間的共享記憶體通信,也就是說每個共享記憶體區域對應特殊檔案系統shm中的一個檔案。
另外,我們還必須了解RSS、PSS、USS等相關概念:
- VSS – Virtual Set Size 虛拟耗用記憶體(包含共享庫占用的記憶體)
- RSS – Resident Set Size 實際使用實體記憶體(包含共享庫占用的記憶體)
- PSS – Proportional Set Size 實際使用的實體記憶體(比例配置設定共享庫占用的記憶體)
- USS – Unique Set Size 程序獨自占用的實體記憶體(不包含共享庫占用的記憶體)
RSS(Resident set size),使用top指令可以查詢到,是最常用的記憶體名額,表示程序占用的實體記憶體大小。但是,将各程序的RSS值相加,通常會超出整個系統的記憶體消耗,這是因為RSS中包含了各程序間共享的記憶體。
PSS(Proportional set size)所有使用某共享庫的程式均分該共享庫占用的記憶體時,每個程序占用的記憶體。顯然所有程序的PSS之和就是系統的記憶體使用量。它會更準确一些,它将共享記憶體的大小進行平均後,再分攤到各程序上去。
USS(Unique set size )程序獨自占用的記憶體,它是PSS中自己的部分,它隻計算了程序獨自占用的記憶體大小,不包含任何共享的部分。
是以下面介紹的指令,有些檢視程序的虛拟記憶體使用,有些是檢視程序的RSS或實際實體記憶體。在講述的時候,我們會标注這些資訊。
top指令檢視
執行top指令後,執行SHIFT +F ,可以選擇按某列排序,例如選擇n後,就會按字段%MEM排序
當然也可以使用shift+m 或大寫鍵M 讓top指令按字段%MEM來排序,當然你也可以按VIRT(虛拟記憶體)、SWAP(程序使用的SWAP空間)、RES(實際使用實體記憶體,當然這裡由于涉及共享記憶體緣故,你看到的實際記憶體非常大)
%MEM — Memory usage (RES)
A task’s currently used share of available physical memory
VIRT — virtual memory
The total amount of virtual memory used by the task. It includes all code, data and shared libraries plus pages that have been swapped out. (Note: you can define the STATSIZE=1 environment variable and the VIRT will be calculated from the /proc/#/state VmSize field.)
VIRT = SWAP + RES
SWAP — Swapped size (kb)
The swapped out portion of a task’s total virtual memory image.
RES — Resident size (kb)
RES = CODE + DATA.
是否有人會覺得奇怪,為什麼%MEM這一列的值加起來會大于100呢? 這個是因為這裡計算的時候包含了共享記憶體的緣故,另外由于共享記憶體的緣故,你看到程序使用VIRT或RES都非常高。由于大部分的實體記憶體通常在多個應用程式之間共享,名為實際使用實體記憶體(RSS,對應top指令裡面的RES)的這個标準的記憶體耗用衡量名額會大大高估記憶體耗用情況。
ps指令檢視
使用ps指令找出占用記憶體資源最多的20個程序(數量可以任意設定)
# ps aux | head -1;ps aux |grep -v PID |sort -rn -k +4 | head -20
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
oracle 32147 11.0 51.2 13252080 12666320 ? Rs Aug24 163:16 ora_s000_SCM2
oracle 32149 14.2 50.9 13250344 12594264 ? Ss Aug24 210:41 ora_s001_SCM2
oracle 32153 4.2 49.6 13250820 12279432 ? Ss Aug24 62:27 ora_s003_SCM2
oracle 32155 2.5 48.6 13250268 12040732 ? Ss Aug24 38:21 ora_s004_SCM2
oracle 32157 1.2 44.5 13250296 11011708 ? Ss Aug24 18:31 ora_s005_SCM2
oracle 32151 2.7 39.7 13350436 9829944 ? Ss Aug24 41:18 ora_s002_SCM2
oracle 32159 0.5 38.9 13250704 9625764 ? Ss Aug24 8:18 ora_s006_SCM2
oracle 32161 0.2 26.3 13250668 6507244 ? Ss Aug24 3:38 ora_s007_SCM2
oracle 32129 0.0 25.5 13299084 6324644 ? Ss Aug24 1:25 ora_dbw0_SCM2
oracle 32181 0.0 15.8 13250152 3913260 ? Ss Aug24 0:56 ora_s017_SCM2
oracle 32145 2.7 15.3 13255256 3786456 ? Ss Aug24 40:11 ora_d000_SCM2
oracle 32127 0.0 15.2 13248996 3762860 ? Ss Aug24 0:05 ora_mman_SCM2
oracle 32163 0.0 14.2 13250108 3525160 ? Ss Aug24 1:04 ora_s008_SCM2
oracle 32165 0.0 8.1 13250172 2007704 ? Ss Aug24 0:37 ora_s009_SCM2
oracle 32169 0.0 6.6 13250060 1656864 ? Ss Aug24 0:08 ora_s011_SCM2
oracle 32177 0.0 6.0 13250148 1498760 ? Ss Aug24 0:12 ora_s015_SCM2
oracle 32187 0.0 5.1 13250084 1267384 ? Ss Aug24 0:06 ora_s020_SCM2
oracle 32179 0.0 5.1 13250584 1280156 ? Ss Aug24 0:05 ora_s016_SCM2
oracle 32167 0.0 5.0 13250060 1248668 ? Ss Aug24 0:08 ora_s010_SCM2
oracle 32175 0.0 3.4 13250596 857380 ? Ss Aug24 0:03 ora_s014_SCM2
#ps -eo pmem,pcpu,rss,vsize,args | sort -k 1 -n -r | less
檢視程序占用的實際實體記憶體(與smem看到實際實體記憶體大小有出入,這裡解釋一下:SIZE: 程序使用的位址空間, 如果程序映射了100M的記憶體, 程序的位址空間将報告為100M記憶體. 事實上, 這個大小不是一個程式實際使用的記憶體數. 是以這裡看到的記憶體跟smem看到的大小有出入)
ps -eo size,pid,user,command --sort -size | awk '{ hr=$1/1024 ; printf("%13.2f Mb