如何迅速分析內(nèi)存的性能瓶頸
通常先運(yùn)行幾個覆蓋面比較大的性能工具,如 free,top,vmstat,pidstat 等
- 先用 free 和 top 查看系統(tǒng)整體內(nèi)存使用情況
- 再用 vmstat 和 pidstat,查看一段時間的趨勢,從而判斷內(nèi)存問題的類型
- 最后進(jìn)行詳細(xì)分析,比如內(nèi)存分配分析,緩存/緩沖區(qū)分析,具體進(jìn)程的內(nèi)存使用分析等
常見的優(yōu)化思路:
- 最好禁止 Swap,若必須開啟則盡量降低 swappiness 的值
- 減少內(nèi)存的動態(tài)分配,如可以用內(nèi)存池,HugePage 等
- 盡量使用緩存和緩沖區(qū)來訪問數(shù)據(jù)。如用堆棧明確聲明內(nèi)存空間來存儲需要緩存的數(shù)據(jù),或者用 Redis 外部緩存組件來優(yōu)化數(shù)據(jù)的訪問
- cgroups 等方式來限制進(jìn)程的內(nèi)存使用情況,確保系統(tǒng)內(nèi)存不被異常進(jìn)程耗盡
- /proc/pid/oom_adj 調(diào)整核心應(yīng)用的 oom_score,保證即使內(nèi)存緊張核心應(yīng)用也不會被OOM殺死
vmstat 使用詳解
vmstat 命令是最常見的 Linux/Unix 監(jiān)控工具,可以展現(xiàn)給定時間間隔的服務(wù)器的狀態(tài)值,包括服務(wù)器的 CPU 使用率,內(nèi)存使用,虛擬內(nèi)存交換情況,IO讀寫情況??梢钥吹秸麄€機(jī)器的 CPU,內(nèi)存,IO 的使用情況,而不是單單看到各個進(jìn)程的 CPU 使用率和內(nèi)存使用率(使用場景不一樣)。
vmstat 2
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 0 1379064 282244 11537528 0 0 3 104 0 0 3 0 97 0 0
0 0 0 1372716 282244 11537544 0 0 0 24 4893 8947 1 0 98 0 0
0 0 0 1373404 282248 11537544 0 0 0 96 5105 9278 2 0 98 0 0
0 0 0 1374168 282248 11537556 0 0 0 0 5001 9208 1 0 99 0 0
0 0 0 1376948 282248 11537564 0 0 0 80 5176 9388 2 0 98 0 0
0 0 0 1379356 282256 11537580 0 0 0 202 5474 9519 2 0 98 0 0
1 0 0 1368376 282256 11543696 0 0 0 0 5894 8940 12 0 88 0 0
1 0 0 1371936 282256 11539240 0 0 0 10554 6176 9481 14 1 85 1 0
1 0 0 1366184 282260 11542292 0 0 0 7456 6102 9983 7 1 91 0 0
1 0 0 1353040 282260 11556176 0 0 0 16924 7233 9578 18 1 80 1 0
0 0 0 1359432 282260 11549124 0 0 0 12576 5495 9271 7 0 92 1 0
0 0 0 1361744 282264 11549132 0 0 0 58 8606 15079 4 2 95 0 0
1 0 0 1367120 282264 11549140 0 0 0 2 5716 9205 8 0 92 0 0
0 0 0 1346580 282264 11562644 0 0 0 70 6416 9944 12 0 88 0 0
0 0 0 1359164 282264 11550108 0 0 0 2922 4941 8969 3 0 97 0 0
1 0 0 1353992 282264 11557044 0 0 0 0 6023 8917 15 0 84 0 0
# 結(jié)果說明
- r 表示運(yùn)行隊列(就是說多少個進(jìn)程真的分配到CPU),我測試的服務(wù)器目前CPU比較空閑,沒什么程序在跑,當(dāng)這個值超過了CPU數(shù)目,就會出現(xiàn)CPU瓶頸了。這個也和top的負(fù)載有關(guān)系,一般負(fù)載超過了3就比較高,超過了5就高,超過了10就不正常了,服務(wù)器的狀態(tài)很危險。top的負(fù)載類似每秒的運(yùn)行隊列。如果運(yùn)行隊列過大,表示你的CPU很繁忙,一般會造成CPU使用率很高。
- b 表示阻塞的進(jìn)程,這個不多說,進(jìn)程阻塞,大家懂的。
- swpd 虛擬內(nèi)存已使用的大小,如果大于0,表示你的機(jī)器物理內(nèi)存不足了,如果不是程序內(nèi)存泄露的原因,那么你該升級內(nèi)存了或者把耗內(nèi)存的任務(wù)遷移到其他機(jī)器。
- free 空閑的物理內(nèi)存的大小,我的機(jī)器內(nèi)存總共8G,剩余3415M。
- buff Linux/Unix系統(tǒng)是用來存儲,目錄里面有什么內(nèi)容,權(quán)限等的緩存,我本機(jī)大概占用300多M
- cache cache直接用來記憶我們打開的文件,給文件做緩沖,我本機(jī)大概占用300多M(這里是Linux/Unix的聰明之處,把空閑的物理內(nèi)存的一部分拿來做文件和目錄的緩存,是為了提高 程序執(zhí)行的性能,當(dāng)程序使用內(nèi)存時,buffer/cached會很快地被使用。)
- si 每秒從磁盤讀入虛擬內(nèi)存的大小,如果這個值大于0,表示物理內(nèi)存不夠用或者內(nèi)存泄露了,要查找耗內(nèi)存進(jìn)程解決掉。我的機(jī)器內(nèi)存充裕,一切正常。
- so 每秒虛擬內(nèi)存寫入磁盤的大小,如果這個值大于0,同上。
- bi 塊設(shè)備每秒接收的塊數(shù)量,這里的塊設(shè)備是指系統(tǒng)上所有的磁盤和其他塊設(shè)備,默認(rèn)塊大小是1024byte,我本機(jī)上沒什么IO操作,所以一直是0,但是我曾在處理拷貝大量數(shù)據(jù)(2-3T)的機(jī)器上看過可以達(dá)到140000/s,磁盤寫入速度差不多140M每秒
- bo 塊設(shè)備每秒發(fā)送的塊數(shù)量,例如我們讀取文件,bo就要大于0。bi和bo一般都要接近0,不然就是IO過于頻繁,需要調(diào)整。
- in 每秒CPU的中斷次數(shù),包括時間中斷
- cs 每秒上下文切換次數(shù),例如我們調(diào)用系統(tǒng)函數(shù),就要進(jìn)行上下文切換,線程的切換,也要進(jìn)程上下文切換,這個值要越小越好,太大了,要考慮調(diào)低線程或者進(jìn)程的數(shù)目,例如在apache和nginx這種web服務(wù)器中,我們一般做性能測試時會進(jìn)行幾千并發(fā)甚至幾萬并發(fā)的測試,選擇web服務(wù)器的進(jìn)程可以由進(jìn)程或者線程的峰值一直下調(diào),壓測,直到cs到一個比較小的值,這個進(jìn)程和線程數(shù)就是比較合適的值了。系統(tǒng)調(diào)用也是,每次調(diào)用系統(tǒng)函數(shù),我們的代碼就會進(jìn)入內(nèi)核空間,導(dǎo)致上下文切換,這個是很耗資源,也要盡量避免頻繁調(diào)用系統(tǒng)函數(shù)。上下文切換次數(shù)過多表示你的CPU大部分浪費(fèi)在上下文切換,導(dǎo)致CPU干正經(jīng)事的時間少了,CPU沒有充分利用,是不可取的。
- us 用戶CPU時間,我曾經(jīng)在一個做加密解密很頻繁的服務(wù)器上,可以看到us接近100,r運(yùn)行隊列達(dá)到80(機(jī)器在做壓力測試,性能表現(xiàn)不佳)。
- sy 系統(tǒng)CPU時間,如果太高,表示系統(tǒng)調(diào)用時間長,例如是IO操作頻繁。
- id 空閑CPU時間,一般來說,id + us + sy = 100,一般我認(rèn)為id是空閑CPU使用率,us是用戶CPU使用率,sy是系統(tǒng)CPU使用率。
- wt 等待IO CPU時間
pidstat 使用詳解
pidstat 主要用于監(jiān)控全部或指定進(jìn)程占用系統(tǒng)資源的情況,如CPU,內(nèi)存、設(shè)備IO、任務(wù)切換、線程等。
使用方法:
- pidstat –d interval times 統(tǒng)計各個進(jìn)程的IO使用情況
- pidstat –u interval times 統(tǒng)計各個進(jìn)程的CPU統(tǒng)計信息
- pidstat –r interval times 統(tǒng)計各個進(jìn)程的內(nèi)存使用信息
- pidstat -w interval times 統(tǒng)計各個進(jìn)程的上下文切換
- p PID 指定PID
1、統(tǒng)計 IO 使用情況
pidstat -d 1 10
03:02:02 PM UID PID kB_rd/s kB_wr/s kB_ccwr/s Command
03:02:03 PM 0 816 0.00 918.81 0.00 jbd2/vda1-8
03:02:03 PM 0 1007 0.00 3.96 0.00 AliYunDun
03:02:03 PM 997 7326 0.00 1904.95 918.81 java
03:02:03 PM 997 8539 0.00 3.96 0.00 java
03:02:03 PM 0 16066 0.00 35.64 0.00 cmagent
03:02:03 PM UID PID kB_rd/s kB_wr/s kB_ccwr/s Command
03:02:04 PM 0 816 0.00 1924.00 0.00 jbd2/vda1-8
03:02:04 PM 997 7326 0.00 11156.00 1888.00 java
03:02:04 PM 997 8539 0.00 4.00 0.00 java
- UID
- PID
- kB_rd/s:每秒進(jìn)程從磁盤讀取的數(shù)據(jù)量 KB 單位 read from disk each second KB
- kB_wr/s:每秒進(jìn)程向磁盤寫的數(shù)據(jù)量 KB 單位 write to disk each second KB
- kB_ccwr/s:每秒進(jìn)程向磁盤寫入,但是被取消的數(shù)據(jù)量,This may occur when the task truncates some dirty pagecache.
- iodelay:Block I/O delay,measured in clock ticks
- Command:進(jìn)程名 task name
2、統(tǒng)計 CPU 使用情況
# 統(tǒng)計CPU
pidstat -u 1 10
03:03:33 PM UID PID %usr %system %guest %CPU CPU Command
03:03:34 PM 0 2321 3.96 0.00 0.00 3.96 0 ansible
03:03:34 PM 0 7110 0.00 0.99 0.00 0.99 4 pidstat
03:03:34 PM 997 8539 0.99 0.00 0.00 0.99 5 java
03:03:34 PM 984 15517 0.99 0.00 0.00 0.99 5 java
03:03:34 PM 0 24406 0.99 0.00 0.00 0.99 5 java
03:03:34 PM 0 32158 3.96 0.00 0.00 3.96 2 ansible
- UID
- PID
- %usr: 進(jìn)程在用戶空間占用 cpu 的百分比
- %system: 進(jìn)程在內(nèi)核空間占用 CPU 百分比
- %guest: 進(jìn)程在虛擬機(jī)占用 CPU 百分比
- %wait: 進(jìn)程等待運(yùn)行的百分比
- %CPU: 進(jìn)程占用 CPU 百分比
- CPU: 處理進(jìn)程的 CPU 編號
- Command: 進(jìn)程名
3、統(tǒng)計內(nèi)存使用情況
# 統(tǒng)計內(nèi)存
pidstat -r 1 10
Average: UID PID minflt/s majflt/s VSZ RSS %MEM Command
Average: 0 1 0.20 0.00 191256 3064 0.01 systemd
Average: 0 1007 1.30 0.00 143256 22720 0.07 AliYunDun
Average: 0 6642 0.10 0.00 6301904 107680 0.33 java
Average: 997 7326 10.89 0.00 13468904 8395848 26.04 java
Average: 0 7795 348.15 0.00 108376 1233 0.00 pidstat
Average: 997 8539 0.50 0.00 8242256 2062228 6.40 java
Average: 987 9518 0.20 0.00 6300944 1242924 3.85 java
Average: 0 10280 3.70 0.00 807372 8344 0.03 aliyun-service
Average: 984 15517 0.40 0.00 6386464 1464572 4.54 java
Average: 0 16066 236.46 0.00 2678332 71020 0.22 cmagent
Average: 995 20955 0.30 0.00 6312520 1408040 4.37 java
Average: 995 20956 0.20 0.00 6093764 1505028 4.67 java
Average: 0 23936 0.10 0.00 5302416 110804 0.34 java
Average: 0 24406 0.70 0.00 10211672 2361304 7.32 java
Average: 0 26870 1.40 0.00 1470212 36084 0.11 promtail
- UID
- PID
- Minflt/s : 每秒次缺頁錯誤次數(shù) (minor page faults),虛擬內(nèi)存地址映射成物理內(nèi)存地址產(chǎn)生的 page fault 次數(shù)
- Majflt/s : 每秒主缺頁錯誤次數(shù) (major page faults), 虛擬內(nèi)存地址映射成物理內(nèi)存地址時,相應(yīng) page 在 swap 中
- VSZ virtual memory usage : 該進(jìn)程使用的虛擬內(nèi)存 KB 單位
- RSS : 該進(jìn)程使用的物理內(nèi)存 KB 單位
- %MEM : 內(nèi)存使用率
- Command : 該進(jìn)程的命令 task name
4、查看具體進(jìn)程使用情況
pidstat -T ALL -r -p 20955 1 10
03:12:16 PM UID PID minflt/s majflt/s VSZ RSS %MEM Command
03:12:17 PM 995 20955 0.00 0.00 6312520 1408040 4.37 java
03:12:16 PM UID PID minflt-nr majflt-nr Command
03:12:17 PM 995 20955 0 0 java
-End-
-
緩沖區(qū)
+關(guān)注
關(guān)注
0文章
33瀏覽量
9107 -
數(shù)據(jù)
+關(guān)注
關(guān)注
8文章
7002瀏覽量
88938 -
SWAP
+關(guān)注
關(guān)注
0文章
51瀏覽量
12820 -
堆棧
+關(guān)注
關(guān)注
0文章
182瀏覽量
19753 -
Redis
+關(guān)注
關(guān)注
0文章
374瀏覽量
10871
發(fā)布評論請先 登錄
相關(guān)推薦
評論