Home 浅谈系统性能的工作流
Post
Cancel

浅谈系统性能的工作流

半年前翻了Systems Performance(性能之巅)的一小部分,现在进一步阅读并做点复查用的笔记。

目前打算是分成两篇,一篇介绍基本理论,另一篇介绍工作流。本篇为工作流。

注意这里提到的是系统性能存在异常时的工作流,不涉及稳定性和常规性能优化。

保命声明:显然这是一个很有深度的话题,然而笔者的水平只能浅到不能再浅了……
免责声明:这是一篇未完工的文章!

用工具观测资源

tools 非常著名的工具大全

上一篇文章介绍用于性能分析的USE方法:从资源的利用率、饱和度和错误去看待性能。是否存在性能问题主要看饱和度和错误:若存在性能问题,必有过饱和或者错误;若未存在性能问题,可以通过排队论对利用率的临界点进行预测。再直白点说,如果在系统中想要获取某一项资源,但是获取的过程发生了停顿等待(排队)的行为,那就是存在性能问题。

观测资源则需要用到工具。但是如上图所示,工具(还有指标)的选择非常多,不同背景的开发者对资源的划分也有不同的见解,因此还是要准备一份适合自己的工作流。

NOTE: 上一篇文章也提到PSI是一个非常好用的系统压力指标,可以避免各种工具的学习成本,这里不再重复介绍了。

CPU

CPU的主要性能指标有:平均负载(load average)、CPU使用率(CPU usage,%CPU)和IPC(instructions per cycle)。

平均负载跟踪处于 TASK_RUNNING (R) 加上 TASK_UNIERRUPTED (D) 状态的任务数目,并且按照每1分钟、5分钟和15分钟的粒度给出三个平滑处理过的数值。这些数据用于动态观察系统整体负载(计算负载和IO负载)的变化趋势。(这里负载指的是需要运行处理但是可能允许排队的任务。)有两个诊断用的经验方法:理想状态认为数值低于CPU数目;高于70%CPU数目则认为是高负载。该指标可以使用uptimetop或者cat /proc/loadavg命令获取。如果需要统计分离的R状态和D状态的任务数目,可以使用dstat -p命令获取。

系统级别的CPU使用率划分了不同类型的CPU时间占比,包含usr、nice、sys、iowait、irq、soft和idle等负载类型,按照百分比显示。on-CPU相关需要关注前三项,如果是usr低占比的同时sys高占比,可能存在两种情况:一是用户层的代码足够好,只剩下高占比的系统调用;二是用户层的代码足够差,有大量使用不当的系统调用。该指标可以使用topdstat -c或者cat /proc/stat | grep cpu(需解析)命令获取。每CPU级别可以直接使用mpstat -P ALLsar -P ALL 1或者top交互面板按1命令获取。

任务级别的CPU使用率计算非空闲状态的CPU时间(non-idle time)占比,其结果仅有一个百分比数值,这里的非空闲时间指的是系统时间(stime)加上用户时间(utime)。该指标可以使用top命令获取。

IPC是每时钟周期所执行的平均指令数。有一种说法认为前面提到的非空闲时间不等价于繁忙时间,事实上还可能包含了停顿时间(iowait),也就是不应该使用CPU使用率来衡量CPU繁忙程度,而是使用IPC来衡量。(需要注意系统CPU使用率显示可以细化到多种分类,iowait是可以单独展示的。而任务的CPU使用率只显示一个百分比,是否包含iowait还取决于工具的版本或算法,这里确实是个含糊的地方。)IPC数值的简单划分方式是:IPC小于1.0很可能是出现了停顿问题(off-CPU),而大于等于1.0则至少可认为是正常情况。如果需要更精准的划分,可以自行定制。该指标可以使用perf stat(默认是system wide模式,即-a)或者tiptop命令获取。

Here’s how you can get a value that’s custom for your system and runtime: write two dummy workloads, one that is CPU bound, and one memory bound. Measure their IPC, then calculate their mid point.

Memory

内存的主要性能指标有:内存利用率(%MEM)、页面回收效率(%vmeff)和任务的内存映射区域(smaps)。

内存利用率是容量意义上的利用率。系统级别的内存利用信息都集中在meminfo,其可用内存份额为MemAvailable(一个估算值),系统的利用率可以按照(MemTotal - MemAvailable) / MemTotal计算;任务级别的内存利用率则是按照RSS计算。这些内容的解析可以看这篇文章。该指标可以使用topfree或者cat /proc/meminfo命令获取。

页面回收效率跟踪kswapd页面回收和直接页面回收的压力情况。因为Linux系统本身善用页面缓存(page cache),所以内存利用信息里面统计的MemFree和MemAvailable存在一定数值差距。但是当内存使用存在压力时,可用内存份额是否完全释放出页面缓存作为救急用内存,这还需要观察%vmeff (= pgsteal / (pgscank + pgscand))即页面回收效率。从man page可以了解到,理想状态为100%,但是降低到一定程度如30%就可能是memory bound。该指标可以使用sar -B命令获取。

任务内存映射区域可以按照进程的每个内存区域进行内存信息统计。最简单的分析方法就是查看数值是否符合程序实现的预期。该指标可以使用cat /proc/[pid]/smaps命令获取。

NOTE: 内存的压力有一部分来自缓存,尤其是程序自身实现的缓存,这部分的缓存让系统误判为是一时无法回收的资源。因此在内存利用率上,我们能看到的系统层面的内存统计信息不一定是事实正确的。比如meminfo提示可用内存份额已经小于10MB,但是实际上有高达10GB的程序缓存可以直接释放,这是系统层面无法直接得知的信息。因此,这方面的分析我觉得需要程序自行实现缓存信息统计的工具或命令。

TODO: 关于PSS和RSS的选择。工具一般提供RSS作为默认选择,但是Android平台经常是以PSS的形式给出。我也不知道谷歌的想法……调研待办。

Disk

通常IO设备(包括硬盘)有三个主要性能指标:IOPS、吞吐量和延迟。虽然指标的含义人尽皆知,但是我寻思这些指标是写到PPT里给大老板看的。

latency 延迟的粒度

对于系统性能分析来说,这里也许有进一步讨论的价值:

  1. 从IO特征的角度来看,吞吐量描述了不同的IO块大小乘上对应的IOPS的累计结果。反过来说,吞吐量作为计算后的结果其实忽视了IO特征中块大小的分布信息。
  2. 延迟指标也有粒度上的问题,见上图,如果IO生命周期只有一个从开始到结束的延迟统计信息,那就难以发现是哪一个层面出现的性能问题。
  3. 无论是IOPS、吞吐量还是延迟,它们都是针对已经完成的IO操作而言的,还没考虑到尚未完成的IO操作,因此还需要观察排队压力情况,也就是IO队列长度
  4. 同样是IO特征,不同的业务场景会影响到IO的读写比例(不考虑DISCARD这种麻烦要素)。如果存在异常的比例倾斜,我们可以直接定位是IO性能问题,节省对其它指标的分析时间。

上面加粗的文字部分是需要额外考虑的性能指标。

命令TODO,简单列上:

  • sar -d
  • iostat -x
  • blktrace & btt
  • iotop(CONFIG_TASK_DELAY_ACCT)
  • bcc-tools/bio[阿巴阿巴]
blkparse的延迟统计粒度:

 Q------->G------------>I--------->M------------------->D----------------------------->C
 |-Q time-|-Insert time-|
 |--------- merge time ------------|-merge with other IO|
 |----------------scheduler time time-------------------|---driver,adapter,storagetime--|
 
 |----------------------- await time in iostat output ----------------------------------|

Q2Q — time between requests sent to the block layer
Q2G — time from a block I/O is queued to the time it gets a request allocated for it
G2I — time from a request is allocated to the time it is Inserted into the device's queue
Q2M — time from a block I/O is queued to the time it gets merged with an existing request
I2D — time from a request is inserted into the device's queue to the time it is actually issued to the device
M2D — time from a block I/O is merged with an exiting request until the request is issued to the device
D2C — service time of the request by the device
Q2C — total time spent in the block layer for a request

!!!!! WORK IN PROGRESS !!!!!
!!!!! WORK IN PROGRESS !!!!!
!!!!! WORK IN PROGRESS !!!!!

还有好多内容要写,容我歇一会orz

References

Systems Performance, 2nd Edition
Linux Load Averages: Solving the Mystery – Brendan Gregg’s Blog
CPU Utilization is Wrong – Brendan Gregg’s Blog
top中CPU使用率计算原理 – 知乎
sar man page on SuSE – Polarhome
内存管理概览 – Android Developers
Block I/O Layer Tracing: blktrace – Hewlett-­Packard Company
blktrace分析IO – Bean Li
Block Layer Observability with bcc-tools – Oracle Linux Blog
XRP: In-Kernel Storage Functions with eBPF – USENIX

This post is licensed under CC BY 4.0 by the author.
Contents