Linux工具性能調優系列三:swap問題定位

一,預備知識

1.1 什麼是swap

swap當咱們指的名詞的時候,它能夠是一個分區,也能夠是一個文件,是操做系統中一個存放從內存中置換出的數據的地方。 當咱們指的是一個動詞時候,表明的是從物理內存交換數據到swap分區這個動做。linux

1.2 爲何會swap

(1) 當物理內存不夠用時候,會根據特定的算法,把一部份內存交換到swap分區(此時還會伴隨着高IO)。可是並非全部的內存均可以被交換到swap分區。 (2) kswapd進程週期性對內存進行檢查,若是發現高於水位線,則觸發swap,此舉是爲了避免讓系統剩餘內存不多,防止出現忽然的大內存申請。這塊暫不深刻講解,後續再補充。ios

1.3 swap的究竟是什麼

首先咱們要知道,內存管理將內存分爲active和inactive,進程用戶空間使用的映射包括了匿名映射(anon)和文件映射(file)。全部一共有active anon,inactive anon,active file,inactive file。對於文件映射,因爲自己是磁盤空間中的文件,全部它不會被swap,當須要釋放時候,髒數據直接寫回磁盤,其餘數據直接釋放便可。內存交換到swap,確定是交換不活躍的數據,全部,inactive anon是最主要的被交換的內存。那麼對於操做系統來講,當我須要回收內存時候,你說它是針對文件映射好,仍是針對匿名映射好,這就涉及到了一個參數:swapinessgit

1.3.1 swapiness

swapiness是設置內存回收時候,更傾向於回收文件映射仍是匿名映射,在/proc/sys/vm/swappiness設置值。對於swapiness=100,那麼二者之間的權重是一致的,值越小,越傾向於回收文件映射,不過若是達到系統高水位線,仍是會swap,除非直接使用swapoff -a等手段關閉系統swap。github

1.3 swap的好壞

swap的好處是當內存不足時候,能夠將一部分交換出去,不會觸發oom-killer。跑得慢總比不能跑好。 swap的壞處是交換時候,會觸發高IO,同時會下降系統的性能。對於咱們隔離作的很差的時候,會影響到其餘應用的性能。golang

二,工具選擇

一個工具每每具備多種用途,可是本文只說明針對swap問題算法

工具名稱 使用姿式 採集指標來源
free free -h /proc/meminfo
top 按f,選擇swap /proc/$pid/smaps
vmstat vmstat /proc/meminfo
iotop iotop
iostat iostat -xdm
pidstat pidstat -d 1 /proc/$pid/io

三,案例分析

3.1 應用一直申請內存

本次的案例是使用golang編寫,在一個死循環裏面,每次循環申請內存,而且不釋放,而後達到必定次數後釋放內存,等待GC,再繼續,代碼和文檔歸檔在:歸檔docker

3.1.1 運行程序和分析

(1) 運行api

root@szdc-calic-2-6:/www/linuxperformancetool/swap# ./swapexample1
複製代碼

因爲上面說的命令均可以用於分析,你們根據喜愛搭配使用便可。我這裏用top,vmstat和pidstat搭配使用進行分析,能夠開多幾個終端一塊兒看。bash

(2) 分析 首先是使用vmstat,從下面能夠看出,當程序佔用內存愈來愈大時候,出現了很高的swap io和block io,想一下,爲何這兩個同時都增高?app

root@szdc-calic-2-6:~# vmstat -a 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free  inact active   si   so    bi    bo   in   cs us sy id wa st
 1  0 1240208 18816440 715216 12702360    0    0     1    18    0    0  0  0 99  0  0
 1  0 1240208 18086504 715220 13431988    0    0     0     0 2223 3192  1  4 96  0  0
 1  0 1240208 17343176 715220 14173444    0    0     0    60 1906 3099  1  4 95  0  0
 1  0 1240208 16618392 715260 14897140    0    0     0    60 2351 3552  1  4 96  0  0
 1  0 1240208 15883220 715280 15632572    0    0     0     0 2187 3547  1  4 96  0  0
 0  2 1240300 15276012 806532 16151868    0   92     0  2088 2365 3373  1  3 95  2  0
 0  2 1265792 15270100 2023920 14946200   56 25500   100 27536 5102 9189  1  1 93  5  0
 0  3 1265784 15274476 2023856 14944732   40    0    40  2572 2162 2425  0  0 90 10  0
 0  9 1287036 15276116 2022816 14944232   88 21276    88 22228 2074 3136  0  0 79 21  0
 0  9 1287020 15273676 2024776 14946436   92    0    92  2288 3563 5822  0  0 79 20  0
 2  3 1286912 15271708 2024844 14946532  128    0   128  1432 2989 4907  0  0 84 16  0
 0  3 1286912 15271692 2024572 14946520    0    0     0  2344 3098 4543  0  0 87 13  0
 0  4 1312096 15265788 2022444 14951064    0 25188     0 26628 4946 9752  1  1 90  9  0
複製代碼

發現了系統問題後,咱們就須要對問題進行定位了,這裏可使用top,pidstat,iotop等工具進行定位,我這邊直接使用top,按f選擇swap。

top - 00:52:38 up 253 days, 14:23,  3 users,  load average: 6.44, 2.60, 1.23
Tasks: 359 total,   1 running, 358 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.6 us,  0.6 sy,  0.0 ni, 67.0 id, 31.7 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem : 32895096 total,   236100 free, 32011520 used,   647476 buff/cache
KiB Swap: 31250428 total, 28358956 free,  2891472 used.   261616 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                               SWAP
45466 root      20   0 10.076g  21624   2520 S  12.9  0.1   7881:36 etcd                                                 19636
  146 root      20   0       0      0      0 D   9.2  0.0   2:28.44 kswapd0                                                  0
14179 root      20   0 31.136g 0.029t   4316 S   3.3 94.8   0:31.86 main1                                               1.375g
  147 root      20   0       0      0      0 S   1.7  0.0   1:52.23 kswapd1                                                  0
10737 root      20   0 3067756  60688   5968 S   0.7  0.2   3364:41 dockerd                                              60380
10750 root      20   0 2898452  38724   3096 S   0.7  0.1 629:49.22 docker-containe                                      79288
複製代碼

從top的變化能夠看出,pid=14179的進程一直swap一直在增高,並且內存佔用愈來愈高,其餘進程雖然有出現swap增多,可是內存使用並無增高,能夠判斷,該進程是致使出現swap的緣由。那麼,咱們再進一步進行確認。

使用pidstat判斷該pid的io狀況,能夠看出,是存在很大的IO

root@szdc-calic-2-6:~# pidstat -p 14179 -d 1
Linux 4.4.0-87-generic (szdc-calic-2-6.meitu-inc.com) 	Wednesday, December 12, 2018 	_x86_64_	(24 CPU)

12:55:40 CST   UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s iodelay  Command
12:55:41 CST     0     14179  71920.00      0.00      0.00       0  main1
12:55:42 CST     0     14179  72796.04      0.00      0.00       0  main1
12:55:43 CST     0     14179  85664.00      0.00      0.00       0  main1
12:55:44 CST     0     14179  78128.00      0.00      0.00       0  main1
12:55:45 CST     0     14179  69660.00      0.00      0.00       0  main1
12:55:46 CST     0     14179  59892.00      0.00      0.00       0  main1
複製代碼

3.1.2 問題

這些問題都不會直接進行解答,實在想不出來的,能夠到歸檔項目下面提issue或者在下面評論

(1) 爲何例子中,只是簡單的申請內存,會形成swap io和block io同時增高? (2) 例子中,明明還有剩餘內存未被使用,但是已經開始頻繁進行swap和回收大量內存。 (3) golang gc時候,會把已經swap出去的內存再swap到物理內存中,再進行gc嗎? (4) 上一節中的buffer和cache中包含的是哪些?(匿名頁仍是文件映射)

四,參考文獻

1, linuxperf.com/?p=142

2, cloud.tencent.com/developer/a…

相關文章
相關標籤/搜索