文章目錄
性能分析工具
top
線程的各種狀態:
R 是 Running 或 Runnable 的縮寫,表示進程在 CPU 的就緒隊列中,正在運行或者正在等待運行。
D 是 Disk Sleep 的縮寫,也就是不可中斷狀態睡眠(Uninterruptible Sleep),一般表示進程正在跟硬件交互,並且交互過程不允許被其他進程或中斷打斷。
Z 是 Zombie 的縮寫,如果你玩過“植物大戰殭屍”這款遊戲,應該知道它的意思。它表示殭屍進程,也就是進程實際上已經結束了,但是父進程還沒有回收它的資源(比如進程的描述符、PID 等)。
S 是 Interruptible Sleep 的縮寫,也就是可中斷狀態睡眠,表示進程因爲等待某個事件而被系統掛起。當進程等待的事件發生時,它會被喚醒並進入 R 狀態。
I 是 Idle 的縮寫,也就是空閒狀態,用在不可中斷睡眠的內核線程上。前面說了,硬件交互導致的不可中斷進程用 D 表示,但對某些內核線程來說,它們有可能實際上並沒有任何負載,用 Idle 正是爲了區分這種情況。要注意,D 狀態的進程會導致平均負載升高, I 狀態的進程卻不會。
T 或者 t,也就是 Stopped 或 Traced 的縮寫,表示進程處於暫停或者跟蹤狀態。
X,也就是 Dead 的縮寫,表示進程已經消亡,所以你不會在 top 或者 ps 命令中看到它。
+ 表示前臺進程組
s 表示是一個會話的領導進程
pstree
用法:
# -a 表示輸出命令行選項
# p 表 PID
# s 表示指定進程的父進程
$ pstree -aps 3084
systemd,1
└─dockerd,15006 -H fd://
└─docker-containe,15024 --config /var/run/docker/containerd/containerd.toml
└─docker-containe,3991 -namespace moby -workdir...
└─app,4009
└─(app,3084)
mpstat
用法:
mpstat -P ALL 5 # 查看所有CPU的使用情況
vmstat
用於查看系統中斷和上下文切換此時,就緒隊列的長度等信息
用法:
vmstat 5 # 每5秒輸出一次
pidstat
pidstat -u -w -t 5 10 # 5秒輸出一次,共輸出10次;w:上下文切換次數 t:輸出線程指標 d:進程的IO情況
# 查看IO情況
pidstat -d 1
13:39:51 UID PID kB_rd/s kB_wr/s kB_ccwr/s iodelay Command
13:39:52 102 916 0.00 4.00 0.00 0 rsyslogd
perf
用於查看每個函數或指令的CPU使用情況
用法:
perf top # 實時顯示佔用CPU最多的函數或指令
perf record # 保存數據用於離線分析
perf report # 分析離線數據
示例:
# -g 開啓調用關係分析,-p 指定 php-fpm 的進程號 21515
$ perf top -g -p 21515
proc
cat /proc/interrupts # 查看內核中斷
cat /proc/softirqs # 查看軟中斷
tcpdump
用法:
# -i eth0 只抓取 eth0 網卡,-n 不解析協議名和主機名
# tcp port 80 表示只抓取 tcp 協議並且端口號爲 80 的網絡幀
$ tcpdump -i eth0 -n tcp port 80
15:11:32.678966 IP 192.168.0.2.18238 > 192.168.0.30.80: Flags [S], seq 458303614, win 512, length 0
bcc工具箱
需安裝bcc,並配置PATH路徑:export PATH=$PATH:/usr/share/bcc/tools
,CentOS還需要手動升級內核版本到4.1以上後才能用,升級方法參考:https://www.jianshu.com/p/997e0a6d8e09,或者參考它的 Github 網站https://github.com/iovisor/bcc
cachestat
提供了整個操作系統緩存的讀寫命中情況
用法:
$ cachestat 1 3
TOTAL MISSES HITS DIRTIES BUFFERS_MB CACHED_MB
2 0 2 1 17 279
2 0 2 1 17 279
2 0 2 1 17 279
cachetop
提供了每個進程的緩存命中情況
用法:
$ cachetop
11:58:50 Buffers MB: 258 / Cached MB: 347 / Sort: HITS / Order: ascending
PID UID CMD HITS MISSES DIRTIES READ_HIT% WRITE_HIT%
13029 root python 1 0 0 100.0% 0.0%
memleak
用法:
$ /usr/share/bcc/tools/memleak -p $(pidof app) -a
Attaching to pid 12512, Ctrl+C to quit.
[03:00:41] Top 10 stacks with outstanding allocations:
addr = 7f8f70863220 size = 8192
addr = 7f8f70861210 size = 8192
addr = 7f8f7085b1e0 size = 8192
addr = 7f8f7085f200 size = 8192
addr = 7f8f7085d1f0 size = 8192
40960 bytes in 5 allocations from stack
fibonacci+0x1f [app]
child+0x4f [app]
start_thread+0xdb [libpthread-2.27.so]
filetop
跟蹤內核文件的讀寫情況:
# 切換到工具目錄
$ cd /usr/share/bcc/tools
# -C 選項表示輸出新內容時不清空屏幕
$ ./filetop -C
TID COMM READS WRITES R_Kb W_Kb T FILE
514 python 0 1 0 2832 R 669.txt
514 python 0 1 0 2490 R 667.txt
514 python 0 1 0 2685 R 671.txt
514 python 0 1 0 2392 R 670.txt
514 python 0 1 0 2050 R 672.txt
...
TID COMM READS WRITES R_Kb W_Kb T FILE
514 python 2 0 5957 0 R 651.txt
514 python 2 0 5371 0 R 112.txt
514 python 2 0 4785 0 R 861.txt
514 python 2 0 4736 0 R 213.txt
514 python 2 0 4443 0 R 45.txt
opensnoop
跟蹤內核中的open系統調用,找出打開文件的文件名和路徑:
opensnoop
12280 python 6 0 /tmp/9046db9e-fe25-11e8-b13f-0242ac110002/650.txt
12280 python 6 0 /tmp/9046db9e-fe25-11e8-b13f-0242ac110002/651.txt
12280 python 6 0 /tmp/9046db9e-fe25-11e8-b13f-0242ac110002/652.txt
pcstat
查看指定文件在內存中的緩存大小
該工具基於go語言開發,需安裝go環境:
$ export GOPATH=~/go
$ export PATH=~/go/bin:$PATH
$ go get golang.org/x/sys/unix
$ go get github.com/tobert/pcstat/pcstat
用法:
$ ls
$ pcstat /bin/ls
+---------+----------------+------------+-----------+---------+
| Name | Size (bytes) | Pages | Cached | Percent |
|---------+----------------+------------+-----------+---------|
| /bin/ls | 133792 | 33 | 33 | 100.000 |
+---------+----------------+------------+-----------+---------+
strace
查看進程的系統調用
用法:
# strace -p $(pgrep app) # -f:追蹤多線程
strace: Process 4988 attached
restart_syscall(<\.\.\. resuming interrupted nanosleep \.\.\.>) = 0
openat(AT_FDCWD, "/dev/sdb1", O_RDONLY|O_DIRECT) = 4
mmap(NULL, 33558528, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f448d240000
read(4, "8vq\213\314\264u\373\4\336K\224\25@\371\1\252\2\262\252q\221\n0\30\225bD\252\266@J"\.\.\., 33554432) = 33554432
write(1, "Time used: 0.948897 s to read 33"\.\.\., 45) = 45
close(4) = 0
sar
sar 是一個系統活動報告工具,既可以實時查看系統的當前活動,又可以配置保存和報告歷史統計數據。
用法:
# -n DEV 表示顯示網絡收發的報告,間隔 1 秒輸出一組數據
$ sar -n DEV 1
15:03:46 IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s %ifutil
15:03:47 eth0 12607.00 6304.00 664.86 358.11 0.00 0.00 0.00 0.01
15:03:47 docker0 6302.00 12604.00 270.79 664.66 0.00 0.00 0.00 0.00
15:03:47 lo 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
15:03:47 veth9f6bbcd 6302.00 12604.00 356.95 664.66 0.00 0.00 0.00 0.05
# 間隔 1 秒輸出一組數據
# -r 表示顯示內存使用情況,-S 表示顯示 Swap 使用情況
$ sar -r -S 1
04:39:56 kbmemfree kbavail kbmemused %memused kbbuffers kbcached kbcommit %commit kbactive kbinact kbdirty
04:39:57 6249676 6839824 1919632 23.50 740512 67316 1691736 10.22 815156 841868 4
04:39:56 kbswpfree kbswpused %swpused kbswpcad %swpcad
04:39:57 8388604 0 0.00 0 0.00
04:39:57 kbmemfree kbavail kbmemused %memused kbbuffers kbcached kbcommit %commit kbactive kbinact kbdirty
04:39:58 6184472 6807064 1984836 24.30 772768 67380 1691736 10.22 847932 874224 20
04:39:57 kbswpfree kbswpused %swpused kbswpcad %swpcad
04:39:58 8388604 0 0.00 0 0.00
…
04:44:06 kbmemfree kbavail kbmemused %memused kbbuffers kbcached kbcommit %commit kbactive kbinact kbdirty
04:44:07 152780 6525716 8016528 98.13 6530440 51316 1691736 10.22 867124 6869332 0
04:44:06 kbswpfree kbswpused %swpused kbswpcad %swpcad
04:44:07 8384508 4096 0.05 52 1.27
iostat
查看每塊盤的IO情況,查看每個進程的IO情況使用pidstat
用法:
# -d -x 表示顯示所有磁盤 I/O 的指標
$ iostat -d -x 1
Device r/s w/s rkB/s wkB/s rrqm/s wrqm/s %rrqm %wrqm r_await w_await aqu-sz rareq-sz wareq-sz svctm %util
loop0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
loop1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sda 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sdb 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
iotop
根據IO大小對進程進行排序,類似top
用法:
iotop
Total DISK READ : 0.00 B/s | Total DISK WRITE : 7.85 K/s
Actual DISK READ: 0.00 B/s | Actual DISK WRITE: 0.00 B/s
TID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND
15055 be/3 root 0.00 B/s 7.85 K/s 0.00 % 0.00 % systemd-journald
slabtop
查看緩存大小。
用法:
# 按下 c 按照緩存大小排序,按下 a 按照活躍對象數排序
$ slabtop
Active / Total Objects (% used) : 277970 / 358914 (77.4%)
Active / Total Slabs (% used) : 12414 / 12414 (100.0%)
Active / Total Caches (% used) : 83 / 135 (61.5%)
Active / Total Size (% used) : 57816.88K / 73307.70K (78.9%)
Minimum / Average / Maximum Object : 0.01K / 0.20K / 22.88K
OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME
69804 23094 0% 0.19K 3324 21 13296K dentry
16380 15854 0% 0.59K 1260 13 10080K inode_cache
58260 55397 0% 0.13K 1942 30 7768K kernfs_node_cache
485 413 0% 5.69K 97 5 3104K task_struct
1472 1397 0% 2.00K 92 16 2944K kmalloc-2048
lsof
查看進程打開了哪些文件:
lsof -p 18940
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
python 18940 root cwd DIR 0,50 4096 1549389 /
python 18940 root rtd DIR 0,50 4096 1549389 /
…
python 18940 root 2u CHR 136,0 0t0 3 /dev/pts/0
python 18940 root 3w REG 8,1 117944320 303 /tmp/logtest.txt
其中,FD 表示文件描述符號,TYPE 表示文件類型,NAME 表示文件路徑。
壓力測試工具
ad - HTTP性能壓測工具
ab(apache bench)是一個常用的 HTTP 服務性能測試工具。
安裝方法:
# Ubuntu
$ apt-get install -y apache2-utils
# CentOS
$ yum install -y httpd-tools
測試示例:
# -c 表示併發請求數爲 1000,-n 表示總的請求數爲 10000
$ ab -c 1000 -n 10000 http://192.168.0.30/
...
Server Software: nginx/1.15.8
Server Hostname: 192.168.0.30
Server Port: 80
...
Requests per second: 1078.54 [#/sec] (mean)
Time per request: 927.183 [ms] (mean)
Time per request: 0.927 [ms] (mean, across all concurrent requests)
Transfer rate: 890.00 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 27 152.1 1 1038
Processing: 9 207 843.0 22 9242
Waiting: 8 207 843.0 22 9242
Total: 15 233 857.7 23 9268
Percentage of the requests served within a certain time (ms)
50% 23
66% 24
75% 24
80% 26
90% 274
95% 1195
98% 2335
99% 4663
100% 9268 (longest request)
...
# Time per second:每個請求的延遲,分爲兩行,第一行表示平均延遲,包括了線程運行調度時間和網絡請求響應時間,第二行表示實際請求的響應大小
# Transfer rate:表示吞吐量
hping3 - 網絡包處理能力壓測工具
hping3 是一個可以構造 TCP/IP 協議數據包的工具。
用法:
# -S 參數表示設置 TCP 協議的 SYN(同步序列號),-p 表示目的端口爲 80
# -i u100 表示每隔 100 微秒發送一個網絡幀
# 注:如果你在實踐過程中現象不明顯,可以嘗試把 100 調小,比如調成 10 甚至 1
$ hping3 -S -p 80 -i u100 192.168.0.30
fio - IO壓測工具
文件系統和磁盤IO基準測試工具。
安裝:
# Ubuntu
apt-get install -y fio
# CentOS
yum install -y fio
用法:
# 隨機讀
fio -name=randread -direct=1 -iodepth=64 -rw=randread -ioengine=libaio -bs=4k -size=1G -numjobs=1 -runtime=1000 -group_reporting -filename=/dev/sdb
# 隨機寫
fio -name=randwrite -direct=1 -iodepth=64 -rw=randwrite -ioengine=libaio -bs=4k -size=1G -numjobs=1 -runtime=1000 -group_reporting -filename=/dev/sdb
# 順序讀
fio -name=read -direct=1 -iodepth=64 -rw=read -ioengine=libaio -bs=4k -size=1G -numjobs=1 -runtime=1000 -group_reporting -filename=/dev/sdb
# 順序寫
fio -name=write -direct=1 -iodepth=64 -rw=write -ioengine=libaio -bs=4k -size=1G -numjobs=1 -runtime=1000 -group_reporting -filename=/dev/sdb
各參數的意義:
- direct,表示是否跳過系統緩存。上面示例中,我設置的 1 ,就表示跳過系統緩存。
- iodepth,表示使用異步 I/O(asynchronous I/O,簡稱 AIO)時,同時發出的 I/O 請求上限。在上面的示例中,我設置的是 64。
- rw,表示 I/O 模式。我的示例中, read/write 分別表示順序讀 / 寫,而 randread/randwrite 則分別表示隨機讀 / 寫。
- ioengine,表示 I/O 引擎,它支持同步(sync)、異步(libaio)、內存映射(mmap)、網絡(net)等各種 I/O 引擎。上面示例中,我設置的 libaio 表示使用異步 I/O。
- bs,表示 I/O 的大小。示例中,我設置成了 4K(這也是默認值)。
- filename,表示文件路徑,當然,它可以是磁盤路徑(測試磁盤性能),也可以是文件路徑(測試文件系統性能)。示例中,我把它設置成了磁盤 /dev/sdb。不過注意,用磁盤路徑測試寫,會破壞這個磁盤中的文件系統,所以在使用前,你一定要事先做好數據備份。
報告示例:
read: (g=0): rw=read, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=libaio, iodepth=64
fio-3.1
Starting 1 process
Jobs: 1 (f=1): [R(1)][100.0%][r=16.7MiB/s,w=0KiB/s][r=4280,w=0 IOPS][eta 00m:00s]
read: (groupid=0, jobs=1): err= 0: pid=17966: Sun Dec 30 08:31:48 2018
read: IOPS=4257, BW=16.6MiB/s (17.4MB/s)(1024MiB/61568msec)
slat (usec): min=2, max=2566, avg= 4.29, stdev=21.76
clat (usec): min=228, max=407360, avg=15024.30, stdev=20524.39
lat (usec): min=243, max=407363, avg=15029.12, stdev=20524.26
clat percentiles (usec):
| 1.00th=[ 498], 5.00th=[ 1020], 10.00th=[ 1319], 20.00th=[ 1713],
| 30.00th=[ 1991], 40.00th=[ 2212], 50.00th=[ 2540], 60.00th=[ 2933],
| 70.00th=[ 5407], 80.00th=[ 44303], 90.00th=[ 45351], 95.00th=[ 45876],
| 99.00th=[ 46924], 99.50th=[ 46924], 99.90th=[ 48497], 99.95th=[ 49021],
| 99.99th=[404751]
bw ( KiB/s): min= 8208, max=18832, per=99.85%, avg=17005.35, stdev=998.94, samples=123
iops : min= 2052, max= 4708, avg=4251.30, stdev=249.74, samples=123
lat (usec) : 250=0.01%, 500=1.03%, 750=1.69%, 1000=2.07%
lat (msec) : 2=25.64%, 4=37.58%, 10=2.08%, 20=0.02%, 50=29.86%
lat (msec) : 100=0.01%, 500=0.02%
cpu : usr=1.02%, sys=2.97%, ctx=33312, majf=0, minf=75
IO depths : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.1%, >=64=100.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.1%, >=64=0.0%
issued rwt: total=262144,0,0, short=0,0,0, dropped=0,0,0
latency : target=0, window=0, percentile=100.00%, depth=64
Run status group 0 (all jobs):
READ: bw=16.6MiB/s (17.4MB/s), 16.6MiB/s-16.6MiB/s (17.4MB/s-17.4MB/s), io=1024MiB (1074MB), run=61568-61568msec
Disk stats (read/write):
sdb: ios=261897/0, merge=0/0, ticks=3912108/0, in_queue=3474336, util=90.09%
重點的幾項:
slat ,是指從 I/O 提交到實際執行 I/O 的時長(Submission latency);
clat ,是指從 I/O 提交到 I/O 完成的時長(Completion latency);
lat ,指的是從 fio 創建 I/O 到 I/O 完成的總時長
bw,吞吐量
精確模擬應用程序IO模式:
# 使用 blktrace 跟蹤磁盤 I/O,注意指定應用程序正在操作的磁盤
$ blktrace /dev/sdb
# 查看 blktrace 記錄的結果
# ls
sdb.blktrace.0 sdb.blktrace.1
# 將結果轉化爲二進制文件
$ blkparse sdb -d sdb.bin
# 使用 fio 重放日誌
$ fio --name=replay --filename=/dev/sdb --direct=1 --read_iolog=sdb.bin
pktgen - 網絡性能壓測工具
用於測試網絡性能(PPS,吞吐量),pktgen是作爲一個內核線程來運行的,需要加載pktgen內核模塊,再通過/proc文件系統來交互。
啓動pktgen:
$ modprobe pktgen
$ ps -ef | grep pktgen | grep -v grep
root 26384 2 0 06:17 ? 00:00:00 [kpktgend_0]
root 26385 2 0 06:17 ? 00:00:00 [kpktgend_1]
$ ls /proc/net/pktgen/
kpktgend_0 kpktgend_1 pgctrl
測試示例:
# 定義一個工具函數,方便後面配置各種測試選項
function pgset() {
local result
echo $1 > $PGDEV
result=`cat $PGDEV | fgrep "Result: OK:"`
if [ "$result" = "" ]; then
cat $PGDEV | fgrep Result:
fi
}
# 爲 0 號線程綁定 eth0 網卡
PGDEV=/proc/net/pktgen/kpktgend_0
pgset "rem_device_all" # 清空網卡綁定
pgset "add_device eth0" # 添加 eth0 網卡
# 配置 eth0 網卡的測試選項
PGDEV=/proc/net/pktgen/eth0
pgset "count 1000000" # 總髮包數量
pgset "delay 5000" # 不同包之間的發送延遲 (單位納秒)
pgset "clone_skb 0" # SKB 包複製
pgset "pkt_size 64" # 網絡包大小
pgset "dst 192.168.0.30" # 目的 IP
pgset "dst_mac 11:11:11:11:11:11" # 目的 MAC
# 啓動測試
PGDEV=/proc/net/pktgen/pgctrl
pgset "start"
測試報告示例:
$ cat /proc/net/pktgen/eth0
Params: count 1000000 min_pkt_size: 64 max_pkt_size: 64
frags: 0 delay: 0 clone_skb: 0 ifname: eth0
flows: 0 flowlen: 0
...
Current:
pkts-sofar: 1000000 errors: 0
started: 1534853256071us stopped: 1534861576098us idle: 70673us
...
Result: OK: 8320027(c8249354+d70673) usec, 1000000 (64byte,0frags)
120191pps 61Mb/sec (61537792bps) errors: 0
# Params是測試選項
# Current是測試進度,pkts-sofar(packets so far)表示已經發生了100萬個包
# Result是測試結果,包含測試所用時間、網絡包數量和分片、PPS、吞吐量以及錯誤數
iperf - TCP/UDP吞吐量壓測工具
以客戶端和服務器通信的方式,測試一段時間內的平均吞吐量。
使用方法:
# Ubuntu
apt-get install iperf3
# CentOS
yum install iperf3
# 在服務器端啓動
# -s 表示啓動服務端,-i 表示彙報間隔,-p 表示監聽端口
$ iperf3 -s -i 1 -p 10000
# 在客戶端啓動
# -c 表示啓動客戶端,192.168.0.30 爲目標服務器的 IP
# -b 表示目標帶寬 (單位是 bits/s)
# -t 表示測試時間
# -P 表示併發數,-p 表示目標服務器監聽端口
$ iperf3 -c 192.168.0.30 -b 1G -t 15 -P 2 -p 10000
測試報告實例:
[ ID] Interval Transfer Bandwidth
...
[SUM] 0.00-15.04 sec 0.00 Bytes 0.00 bits/sec sender
[SUM] 0.00-15.04 sec 1.51 GBytes 860 Mbits/sec receiver
# SUM行表示測試的彙總結果,包括測試時間、數據傳輸量和帶寬(吞吐量)
系統知識
內存
- Buffer是對磁盤數據的緩存,Cache是對文件數據的緩存
- 在讀寫普通文件時,會經過文件系統,由文件系統負責與磁盤交互;而讀寫磁盤或者分區時,就會跳過文件系統,也就是所謂的“裸I/O“。這兩種讀寫方式所使用的緩存是不同的,也就是的Cache 和 Buffer 區別
- 降低 Swap 的使用,可以提高系統的整體性能
- 絕大部分 Java 的應用都建議關 swap,這個和 JVM 的 gc 有關,它在 gc 的時候會遍歷所有用到的堆的內存,如果這部分內存是被 swap 出去了,遍歷的時候就會有磁盤IO,參考文章:文章1 文章2
配置swap文件操作
# 創建 Swap 文件
$ fallocate -l 8G /mnt/swapfile
# 修改權限只有根用戶可以訪問
$ chmod 600 /mnt/swapfile
# 配置 Swap 文件
$ mkswap /mnt/swapfile
# 開啓 Swap
$ swapon /mnt/swapfile
# 關閉swap
swapoff -a
# 清理swap空間
swapoff -a && swapon -a
查看內存回收偏好
取值區間爲0-100,數值越大,越積極使用 Swap,也就是更傾向於回收匿名頁;數值越小,越消極使用 Swap,也就是更傾向於回收文件頁。
cat /proc/sys/vm/swappiness
60
查看使用Swap最多的進程
# 按 VmSwap 使用量對進程排序,輸出進程名稱、進程 ID 以及 SWAP 用量
$ for file in /proc/*/status ; do awk '/VmSwap|Name|^Pid/{printf $2 " " $3}END{ print ""}' $file; done | sort -k 3 -n -r | head
dockerd 2226 10728 kB
docker-containe 2251 8516 kB
snapd 936 4020 kB
networkd-dispat 911 836 kB
polkitd 1004 44 kB
磁盤
文件系統
索引節點和目錄項
- 文件系統,本身是對存儲設備上的文件進行組織管理的機制。組織方式不同,就會形成不同的文件系統
- Linux文件系統爲每個文件分配兩個數據結構,索引節點(index node)和目錄項(directory entry)。
- 索引節點:簡稱inode,用來記錄文件的元數據,比如inode編號、文件大小、訪問權限、修改日期、數據的位置等等。索引節點和文件一一對應,並且存儲在磁盤中,佔用磁盤空間。
- 目錄項:簡稱dentry,用來記錄文件的名字、索引節點指針以及其他目錄項的關聯關係,多個關聯的目錄項,就構成了文件系統的目錄結構。目錄項是由內核維護的一個內存數據結構,所以通常也被叫做目錄項緩存,通過磁盤中的數據構建(會根據需要動態構建)。目錄項維護的是系統的樹狀結構。
- 索引節點的容量(即inode的個數),是在格式化磁盤時設定好的,一般由格式化工具自動生成。
- 目錄項和索引節點是多對一關係,爲一個文件創建一個硬鏈接會創建一個目錄項,但不會創建索引節點
- 磁盤讀寫的最小單位是512B,爲了提高效率,文件系統把連續的扇區組成邏輯塊作爲最小單元來管理,常見的邏輯塊大小爲4KB,也就是8個扇區。
- 磁盤在文件系統執行格式化時,會被分成3個存儲區:超級塊、索引節點區和超級塊區
- 超級塊:存儲整個文件系統的狀態
- 索引節點區:存儲索引節點
- 數據塊區:存儲文件數據
- 索引節點、目錄項和磁盤的關係如下圖:
虛擬文件系統
- 目錄項、索引節點、超級塊和邏輯塊構成了Linux文件系統的四大基本要素。
- 文件系統類型包括:基於磁盤的文件系統(Ext4、XFS、OverlayFS 等)、基於內存的文件系統(/proc、/sys等)以及基於網絡的文件系統(NFS、SMB、iSCSI等)
- 爲了支持不同類型的文件系統,Liunx內核在用戶程序和文件系統之間,引入了一個抽象層,也就是虛擬文件系統VFS(Virtual File System)。
- 所有的文件系統都要先掛載到VFS的某個子目錄(掛載點)下,才能訪問其中的文件。
- Linux文件系統架構圖:
文件系統I/O
- 緩衝I/O與非緩衝I/O:利用標準庫緩存來加速文件訪問,而標準庫內部再通過系統調用訪問文件。如很多程序遇到換行時才真正輸出,換行前的內容就是被標準庫暫時緩存起來的;非緩衝IO則直接通過系統調用來訪問文件。
- 直接I/O與非直接IO:非直接IO在進行文件讀寫時,先要經過系統的頁緩存,再由內核或額外的系統調用真正寫入到磁盤中;直接IO則直接跟文件系統交互來訪問文件。
- 裸IO:跳過文件系統,直接寫磁盤。
- 阻塞/非阻塞和同步/異步IO的描述對象不同,阻塞/非阻塞針對的是IO調用者(即應用程序),同步/異步針對的是IO執行者(系統調用)
- 對於機械磁盤和固態磁盤來說,連續IO都要比隨機IO快很多,對於機械磁盤來說,隨機IO需要更多的磁頭尋道和盤片旋轉,固態磁盤也需要先擦除再寫入。另外,連續IO還可以通過預讀的方式來減少IO次數。
- MySql的MyISAM引擎本身只緩存索引,並不緩存數據,需要依賴系統緩存來加速磁盤IO的訪問,但系統緩存並不可靠。應用程序的性能優化並不應該完全建立在系統緩存上,最後能在應用程序的內部分配內存,構建完全自主控制的緩存,MySql的InnoDB引擎就同時緩存了索引和數據;也可以利用第三方緩存應用,比如Memcached,Redis等
磁盤IO
磁盤類型
- 機械磁盤的最小讀寫單位是扇區,一般大小是512B
- 固態磁盤的最小讀寫單位是頁,一般大小是4KB、8KB等
- 不同接口的磁盤設備,一般會被分配不同的名稱前綴,比如IDE接口的設備前綴是hd,SCSI和SATA接口的設備的前綴是sd。
- 把多塊磁盤組成一個邏輯磁盤可以構成冗餘獨立磁盤陣列(RAID)。RAID0具有最優的讀寫性能,但不提供數據冗餘功能,而其它級別的RAID,在提供數據冗餘的基礎上,對讀寫性能也有一定優化。
- 在Linux中,磁盤實際上是作爲一個塊設備來管理的,也就是以塊爲單位讀寫數據。
通用塊層
- 通用塊層是處在文件系統和磁盤驅動之間的一個塊設備抽象層,是Linux磁盤IO的核心。
- 通用塊層向上文件系統和應用程序提供了塊設備的標準接口,向下,把各種異構的塊設備抽象爲統一的塊設備,並提供統一的框架來管理這些設備的驅動程序。通用塊層還會給文件系統和應用程序發來的IO請求排隊,並通過重新排序、請求合併等方式,提供磁盤讀寫的效率。
- 對IO請求的排序過程,就是我們熟悉的IO調度算法。Linux內核支持4中IO調度算法,分別是:NONE(常用語虛擬機),NOOP,CFQ(許多發行版默認的調度算法),DeadLine。
磁盤性能指標
- 五個基本指標:
- 使用率:磁盤處理IO的時間百分比。
- 飽和度:磁盤處理IO的繁忙程度。
- IOPS:每秒的IO請求數。
- 吞吐量:每秒的IO請求大小。
- 響應時間:IO請求從發出到收到響應的時間。
- 在數據庫、大量小文件等這類隨機讀寫比較多的場景中,IOPS更能反映系統的整體性能;而在多媒體等順序讀寫較多的場景中,吞吐量才更能反映系統的整體性能。
- 性能測試工具推薦fio。
- 性能測試需要測試出不同IO大小(一般爲512B~1M的若干中間值)分別在隨機讀、順序讀、隨機寫和順序寫等各種情況下的性能情況。
網絡
性能指標
- 帶寬:表示鏈路的最大傳輸率,單位是b/s
- 吞吐量:表示單位時間內成功傳輸的數據量,單位通常爲b/s或B/s。吞吐量/帶寬=網絡使用率
- 延時:網絡請求發出後,一直到收到遠端響應,所需要的時間延遲
- PPS:Packet Per Second,表示以網絡包爲單位的傳輸速率,通常用來評估網絡的轉發能力,比如硬件交換機,通常可以接近理論最大值,而Linux服務器的轉發,則容易受網絡包大小的影響。千兆交換機的PPS可以達到150萬PPS
- 網絡可用性、併發連接數(TCP連接數量)、丟包率、重傳率也是常用的性能指標
網絡配置
網絡接口狀態
- ifconfig或ip命令可以用來查看接口狀態
- ifconfig的RUNNING或ip的LOWER_UP表示物理網絡是連通的,即網卡已經連接到了交換機或路由器中,否則通常表示網線被拔掉了
- TX和RX的各個指標
- errors:表示發生錯誤的數據包數,比如校驗錯誤、幀同步錯誤等
- dropped:表示丟棄的數據包數,即數據包已經收到了Ring Buffer,但因爲內存不足等原因丟包
- overruns:表示超限數據包數,即網絡IO速度過快,導致Ring Buffer中的數據包來不及處理(隊列滿)而導致丟包
- carrier表示發生carrier錯誤的數據包數,比如雙工模式不匹配、物理電纜出現問題等
- collisions表示碰撞數據包數
性能優化
- DPDK:用戶態網絡標準,它跳過內核協議棧,直接由用戶態進程通過輪詢的方式來處理網絡接收,如果在網絡包很多的情況下(如C10M問題),由於每時每刻都有網絡包需要處理,即使是輪詢效率也很快。DPDK是目前最主流的高性能網絡方案,需要支持DPDK的網卡配合使用
- XDP:允許網絡包在進入內核協議棧之前,就進行處理,也可以帶來更高的性能。基於XDP的應用程序通常是專用的網絡應用,可用於IDS(入侵檢測系統)、DDoS防禦等