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