Linux调优指南

更多相关知识可以阅读:
https://www.yuque.com/treblez/qksu6c/yxl59pkvczqot9us
https://www.yuque.com/treblez/qksu6c/nqe8ip59cwegl6rk
本文不会讲解基础知识。

CPU

设置调度器

Linux调优指南_第1张图片
这几个调度类的优先级如下:Deadline > Realtime > Fair
如果你的某些任务对延迟容忍度很低,比如说在嵌入式系统中就有很多这类任务,那就可以考虑将你的任务设置为实时任务,比如将它设置为 SCHED_FIFO 的任务:$ chrt -f -p 1 1327

使用perf制作火焰图

这里使用FlameGraph这个库(https://github.com/brendangregg/FlameGraph)进行火焰图的绘制

#设置采样率 
export CPUPROFILE_FREQUENCY=4000
export PATH=$PATH:path-to-FlameGraph
#采样
sudo perf record -a -g -F99 --call-graph dwarf -p 51568
sudo perf script > perf.script
sudo stackcollapse-perf.pl perf.script > workrun.floded
sudo flamegraph.pl workrun.floded > workrun.svg

观测cpu指标

  1. top命令

  1. 使用perf观测 CPU Utilization、cycles 和 IPC

分析系统调用

strace 可以跟踪进程的系统调用、特定的系统调用以及系统调用的执行时间。很多时候,我们通过系统调用的执行时间,就能判断出业务延迟发生在哪里。
比如我们想要跟踪一个多线程程序的系统调用情况,那就可以这样使用 strace:

$ strace -T -tt -ff -p pid -o strace.out

内存

观测内存占用

page cache由mmap io和buffered io产生,由内核管理。
Linux调优指南_第2张图片
在 Linux 上直接查看 Page Cache 的方式有很多,包括** /proc/meminfo、free 、/proc/vmstat **命令等,它们的内容其实是一致的。
公式1:Buffers + Cached + SwapCached = Active(file) + Inactive(file) + Shmem + SwapCached

  • SwapCached 是在打开了 Swap 分区后,把 Inactive(anon)+Active(anon) 这两项里的匿名页给交换到磁盘(swap out),然后再读入到内存(swap in)后分配的内存。
  • Page Cache 中的 Shmem 是指匿名共享映射这种方式分配的内存(free 命令中 shared 这一项),比如 tmpfs(临时文件系统[它是一种内存文件系统,只存在于内存中,它无需应用程序去申请和释放内存,而是操作系统自动来规划好一部分空间,应用程序只需要往这里面写入数据就可以了,这样会很方便])、Slab(高速缓存)、KernelStack(内核栈)和 VmallocUsed(内核通过 vmalloc 申请的内存) 这些都是内核分配的,而不是应用程序mmap产生的内存。

公式2:free命令中的buff/cache = Buffers + Cached + SReclaimable

  • SReclaimable 是指可以被回收的内核内存,包括 dentry 和 inode 等。
  • VFS有四个主要对象:超级块对象,对应打开的文件系统;索引节点对象,对应一个具体文件;目录项对象,代表一个路径;文件对象,代表进程打开的文件。可能占用内存较大并且可以被回收的就是索引节点对象inode和目录项对象dentry。

定位内存问题

  1. 观察vmstat指标

  1. 使用tracepoint

Linux调优指南_第3张图片

#首先来使能compcation相关的一些tracepoing
$ echo 1 >
/sys/kernel/debug/tracing/events/compaction/mm_compaction_begin/enable
$ echo 1 >
/sys/kernel/debug/tracing/events/compaction/mm_compaction_end/enable 

#然后来读取信息,当compaction事件触发后就会有信息输出
$ cat /sys/kernel/debug/tracing/trace_pipe
           <...>-49355 [037] .... 1578020.975159: mm_compaction_begin: 
zone_start=0x2080000 migrate_pfn=0x2080000 free_pfn=0x3fe5800 
zone_end=0x4080000, mode=async
           <...>-49355 [037] .N.. 1578020.992136: mm_compaction_end: 
zone_start=0x2080000 migrate_pfn=0x208f420 free_pfn=0x3f4b720 
zone_end=0x4080000, mode=async status=contended

观测脏页和内存回收行为

使用vmstat观察脏页数量

$ cat /proc/vmstat | egrep "dirty|writeback"
    nr_dirty 40
    nr_writeback 2

内存回收流程
Linux调优指南_第4张图片
观察 Page Cache 直接回收和后台回收最简单方便的方式是使用 sar:

$ sar -B 1
02:14:01 PM  pgpgin/s pgpgout/s   fault/s  majflt/s  pgfree/s pgscank/s pgscand/s pgsteal/s    %vmeff


02:14:01 PM      0.14    841.53 106745.40      0.00  41936.13      0.00      0.00      0.00      0.00
02:15:01 PM      5.84    840.97  86713.56      0.00  43612.15    717.81      0.00    717.66     99.98
02:16:01 PM     95.02    816.53 100707.84      0.13  46525.81   3557.90      0.00   3556.14     99.95
02:17:01 PM     10.56    901.38 122726.31      0.27  54936.13   8791.40      0.00   8790.17     99.99
02:18:01 PM    108.14    306.69  96519.75      1.15  67410.50  14315.98     31.48  14319.38     99.80
02:19:01 PM      5.97    489.67  88026.03      0.18  48526.07   1061.53      0.00   1061.42     99.99

下面是这些指标的具体含义:

  • pgscank/s : kswapd(后台回收线程) 每秒扫描的 page 个数。
  • pgscand/s: Application 在内存申请过程中每秒直接扫描的 page 个数。
  • pgsteal/s: 扫描的 page 中每秒被回收的个数。
  • %vmeff: pgsteal/(pgscank+pgscand), 回收效率,越接近 100 说明系统越安全,越接近 0 说明系统内存压力越大。

加快内存页回收

内存页回收的原理
Linux调优指南_第5张图片
调整内存水位
当内存水位低于 watermark low 时,就会唤醒 kswapd 进行后台回收,然后 kswapd 会一直回收到 watermark high。
我们可以增大 min_free_kbytes 这个配置选项来及早地触发后台回收,该选项最终控制的是内存回收水位,对于大于等于 128G 的系统而言,将 min_free_kbytes 设置为 4G 比较合理,这是我们在处理很多这种问题时总结出来的一个经验值,既不造成较多的内存浪费,又能避免掉绝大多数的直接内存回收。
该值的设置和总的物理内存并没有一个严格对应的关系,我们在前面也说过,如果配置不当会引起一些副作用,所以在调整该值之前,我的建议是:你可以渐进式地增大该值,比如先调整为 1G,观察 sar -B 中 pgscand 是否还有不为 0 的情况;如果存在不为 0 的情况,继续增加到 2G,再次观察是否还有不为 0 的情况来决定是否增大,以此类推。
调整脏页的个数
可以通过调小如下设置来将系统脏页个数控制在一个合理范围:

vm.dirty_background_bytes = 0
vm.dirty_background_ratio = 10
vm.dirty_bytes = 0
vm.dirty_expire_centisecs = 3000
vm.dirty_ratio = 20

调整这些配置项有利有弊,调大这些值会导致脏页的积压,但是同时也可能减少了 I/O 的次数,从而提升单次刷盘的效率;调小这些值可以减少脏页的积压,但是同时也增加了 I/O 的次数,降低了 I/O 的效率。

手动回收slab

slab中很大一部分数据是inode:
Linux调优指南_第6张图片
内核提供了如下方法来释放slab:
Linux调优指南_第7张图片
这里注意inode回收的副作用在于对应文件的radix tree中的page cache也会被回收掉,为了避免这种情况,对于重要的数据,可以通过 mlock(2) 来保护它,防止被回收以及被 drop;对于不重要的数据(比如日志),那可以通过 madvise(2) 告诉内核来立即释放这些 Page Cache。

观察进程内存

  1. 通过top观察整个进程的内存占用

Linux调优指南_第8张图片

  1. 通过pmap观察线性地址空间分配
$  pmap -x `pidof sshd`
Address           Kbytes     RSS   Dirty Mode  Mapping 
000055e798e1d000     768     652       0 r-x-- sshd
000055e7990dc000      16      16      16 r---- sshd
000055e7990e0000       4       4       4 rw--- sshd
000055e7990e1000      40      40      40 rw---   [ anon ]
...
00007f189613a000    1800    1624       0 r-x-- libc-2.17.so
00007f18962fc000    2048       0       0 ----- libc-2.17.so
00007f18964fc000      16      16      16 r---- libc-2.17.so
00007f1896500000       8       8       8 rw--- libc-2.17.so
...
00007ffd9d30f000     132      40      40 rw---   [ stack ]
...
  • Mapping,用来表示文件映射中占用内存的文件,比如 sshd 这个可执行文件,或者堆[heap],或者栈[stack],或者其他,等等。
  • Mode,它是该内存的权限,比如,“r-x”是可读可执行,它往往是代码段 (Text Segment);“rw-”是可读可写,这部分往往是数据段 (Data Segment);“r–”是只读,这往往是数据段中的只读部分。
  • Address、Kbytes、RSS、Dirty,Address 和 Kbytes 分别表示起始地址和虚拟内存的大小,RSS(Resident Set Size)则表示虚拟内存中已经分配的物理内存的大小,Dirty 则表示内存中数据未同步到磁盘的字节数。

分析内存泄漏

内存泄漏主要通过meminfo入手:

磁盘

你可能感兴趣的:(linux,驱动开发,运维)