Linux常用性能分析工具彙總

性能分析工具

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防禦等
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章