[转帖]读Brendan Gregg - 谈性能分析

brendan,gregg,性能,分析 · 浏览次数 : 0

小编点评

**数据可视化** * **Heat Map** 用于展示一维数据分布,圆点代表 outliers。 * **Frequency Trail** 用于展示多个分布之间的频率分布。 * **Heat Map** 用于展示二维数据分布,圆点代表 outliers。 * **Performance Trail** 用于展示多个分布之间的性能曲线。 **性能分析平台** * **Atlas Dashboard** 是 Netflix 分析流程的平台,它可以帮助我们分析各种指标,并找到问题所在。 * **USE** 方法应该如何展示? * **Drill Down** 方法应该如何展示? **其他** * **Flame Graph** 是一个用于展示二维数据分布的图表,它可以帮助我们识别出问题所在。 * **Heat Map** 可以用于展示三维数据分布,但它需要使用特定的方法才能进行展示。 * **Frequency Trail** 可以用于展示多个分布之间的频率分布,但它需要使用特定的方法才能进行展示。 * **Performance Trail** 可以用于展示多个分布之间的性能曲线,但它需要使用特定的方法才能进行展示。

正文

https://zhuanlan.zhihu.com/p/206743670

 

Brendan Gregg何许人

Brendan Gregg在性能分析工业界如雷贯耳, 相信看到这篇文章的人肯定知道他的大名. 我们看一下他自己写的bio, 这里摘取的是short版本:

Brendan Gregg is an industry expert in computing performance and cloud computing. He is a senior performance architect at Netflix, where he does performance design, evaluation, analysis, and tuning. He is the author of Systems Performance and BPF Performance Tools (Addison-Wesley), and received the USENIX LISA Award for Outstanding Achievement in System Administration. Brendan has created numerous performance analysis tools, visualizations, and methodologies for performance analysis, including flame graphs.

Brendan Gregg的博客

Brendan的博客内容非常丰富, 总的来说主要包括3个部分:

  • 性能分析的方法论
  • 性能数据的搜集
  • 性能数据的可视化

本文会大量借鉴和引用上面的内容.

性能分析的目的

Brendan博客更关注的是怎么去定位性能问题, 性能分析也可以用于容量规划等, 本文也主要关注前者.

问题分析的方法

每个人在解决问题时都或多或少都有些思路, 当这些思路沉淀下来并能应用到不同的问题上, 便形成了方法论. 作为一个系统工程师, 不管是不是"全栈工程师", 总会碰到不熟悉的系统或者应用, 我们怎么通过对系统的理解, 使用和创造工具, 通过我们的方法论来解决和定位问题.

问题描述

我们从问题本身出发, QA在报一个bug之前, 首先需要确定这是一个bug, 如果是个好QA, 还可以提供更多的信息供开发人员参考:

  • 为什么是个bug? 比如请求延时超过一秒了, 这个不是期望的. 更具体地, 长尾延迟太高或者隔一段时间延迟升高一下. 这样分析人员就可以根据这些信息作出基本判断, 一种可能的情况是这根本就不是一个bug, 而是数据结构就是这样设计的.
  • 是不是regression? regression是一种比较常见的性能问题, 比如在修改了某个系统组件的实现/参数之后, 系统的吞吐下降了. 对于分析人员来讲, 如果能及时发现regression, 这可能会大大减少定位的代价, 如果修改的代码量不多, 或者regression比较稳定, 甚至可能通过git bisect就能定位. 当然不是所有问题都能这样简单解决, 之前我就碰到在将Linux内核版本从2.6.32升级到3.10的时候, application吞吐下降的情况, 这个时候就只能硬刚了, 通过技术层面去定位问题.
  • 系统最近有什么改变? 如果系统一年半载都跑得好好的, 大概率是系统最近有了改变, 可能是系统内部, 也可能是系统外部, 或者系统输入有改变, 知道了这些可以约束问题域. 这也是很多公司即使有很多废代码也不删除的原因, 任何改动都可能产生变化.
  • 系统的软硬件环境, 版本号, 配置信息等也不可或缺, 特别对于性能分析, 这些都不一样的话, 分析无从开始.
  • 问题能否复现. 只要能够在一定的时间内复现, 绝大部分情况下就离定位不远了.

将问题本身描述清楚就是方法的一种, 而且是第一步, 方法并不需要都是高大上的, 它更关注的是普适性.

问题复现

对于很多问题, 特别是复杂的问题, 通过快速地复现问题往往可以事半功倍. 记得多年前, 我们碰到一个很棘手的问题, 当我们好几个人连续几天在不停看日志看代码讨论分析的时候, 公司派了一位资深专家一起来处理这个问题, 他却写了好些小的测试用例试图复现这个问题. 一旦把问题复现了, 那么就有了N份log可以分析, 信息量很可能更多了, 更重要的是可以使用其他的调试手段, trace工具等简化问题. 退一步说, 即使没能复现问题, 也一定程度上排除了一部分可能性, 而且这些东西是可以被看见被量化的, 对个人也是好事, 总有的问题会复杂到不是一时半会能搞定的.

复现问题需要对整个系统有足够理解, 比如两个docker导致cpu cache互相影响的话, 不停地调整目标docker里面的逻辑并不能起到作用. 复现问题关注两个点:

  • 首先要能复现问题. 一个好的问题描述能够帮得上忙, 比如对于docker这个问题, 可能是最近才把另一个docker迁过来的.
  • 再次就是快速复现问题. 一天复现一次和十分钟复现一次对调试的效率是不同的, 为了能够快速复现问题, 我们需要对某些特征进行抽象和简化, 使用这个简化过的程序替代原有的Application.

分而治之

可以简单认为, 一个复杂系统总是由多个子系统组成, 分治是非常自然的想法. 当然怎么切分, 横着切还是竖着切, 从哪个角度切分, 可以多种多样, 很多方法都有分治的影子. 之前碰到过一个linux pxe启动慢的问题, pxe在下载Initrd的时候总是花费比较长的时间, 如果没有明确的证据, 我们不太可能一开始就去看PXE的代码是怎么通过ftfp下载文件的, 这只是整个路径的一部分, 如果我们押宝问题出在pxe代码, 那么这是个收益比较低的猜测. 一种更靠谱的方法是检查网络是否有问题, 当然这也是一种猜测, 但至少可以比较简单进行验证从而给出结论. 更普适的方法是把整个pxe启动相关的流程和组件都画出来, 从而拆解成一个个小问题. 最后我定位到的是tftp server上的目录其实是通过nfs挂载的, 因为代码的每个commit都会在该目录下生成kernel和initrd两个文件, 导致目录下文件异常地多, 而nfs遍历该目录需要很长的时间.

当然这也不是万能的, 分治的核心是要把问题分解(divide)到足够小, 小到我们能够处理(conquer). 这样一个人的能力分为几个部分:

  • 是否能把问题分得足够小的单元
  • 是否能解决相对大的单元, 即使不能继续拆分了
  • 能否建立起单元之间的联系

下图是101围棋网的两个死活题, 都是黑先白死, 左边那个比较简单, 如果能把问题分解到这种程度, 那么我是能hold住, 而右边的那个我既不能继续分解, 作为单个死活单元我也计算不出来, 这就一定程度上决定了我的围棋水平.

上面的图说了局部死活的影响, 另外一部分是怎么把全局分拆, 有的时候这并不是简单的事情. 右上的黑棋和数字棋子之间看似离得很远, 但是却紧密关联.

科学方法

Scientific method是一个不停提出假设和验证的过程, 举例如下:

  1. Question: what is causing slow database queries?
  2. Hypothesis: noisy neighbors (cloud) performing disk I/O, contending with database disk I/O (via the file system)
  3. Prediction: if file system I/O latency is measured during a query, it will show that it is responsible for slow queries
  4. Test: dynamic tracing of database FS latency as a ratio of query latency shows less than 5% is FS
  5. Analysis: FS, and disks, are not responsible for slow queries. Got to 2 and develop a new hypothesis

性能分析的方法

USE

USE关注的是Utilization, Saturation和Errors. USE先列出系统的所有资源, 既可以是硬件资源比如cpu和io, 也可以是锁等软件资源, 然后通过工具获得每个资源的U/S/E信息:

  • Utilization. 资源利用率. 当资源利用率到达一定的阈值时, 比如对于磁盘, 假设请求到达时间遵循泊松分布, 大于70%的利用率就会导致延迟大幅增大. 我们还需要知道utilization的具体含义, 比如ssd上可以处理多个并发请求, 但是某一个时刻只要在服务一个请求就会计算到utilization里面, 所以即使utilization为100%时, 系统仍然可能服务更多的请求.
  • Saturation. 资源饱和度. 一般用队列长度或者延迟表示, 队列长了就会影响到后来的请求. 一个要注意的点是saturation的计算, 如果像iostat那样搜集比如每秒的平均qdepth, 那么对于短时间的burst是感知不到的, 而这恰恰可能是问题所在, 所以我们不只要qdepth的平均值, 还需要更精细的统计.
  • Errors. 发生错误的次数. 错误理论上是比较容易监控, 也是收益比较明显的.

USE会对系统的每个资源生成一个checklist, 这样有两个好处, 一是不容易漏了某个资源, 二是可以在短时间内得出一个结论, 非常时候问题的初步分析阶段.

RED

RED关注的是Rates, Errors和Duration, 和USE从资源的角度不同, RED以微服务处理request出发, 通过简单的规则将不同的微服务统一到相同的指标上, 从而简化问题, 解决scalability of an operations team.

  • (Request) Rate - the number of requests, per second, you services are serving.
  • (Request) Errors - the number of failed requests per second.
  • (Request) Duration - distributions of the amount of time each request takes.

On-CPU

On-CPU的问题, 也就是CPU运行时花了过多时间的问题, 是相对比较简单, 通过采样往往就能发现问题所在. On-CPU的执行时间取决于两个因素:

  • CPU执行的指令. 执行的是否都是有效指令, 比如大量CPU在spinlock, 或者对于LSM tree来说, 大量CPU在做compaction, 我们需要想想compaction本身是否能够优化.
  • 指令的执行时间. 这个指标可以看IPC, IPC是有PMC统计的, 我们也可以通过采样的方法生成火焰图. . 典型的场景比如cache miss或者tlb miss等.

本质上, On-CPU的问题变量比较少, 而且有相对固定的知识和方法, 比如false sharing, 第一次接触可能会没有头绪, 但它终究只是一个知识点. 变量的多少以及相关性直接决定了问题的复杂度, 比如一只南美洲亚马逊河流域热带雨林中的蝴蝶,偶尔扇动几下翅膀,可以在两周以后引起美国得克萨斯州的一场龙卷风, 从德克萨斯的龙卷风反过来推断出其根本原因来源于蝴蝶是相当复杂的.

Off-CPU

和On-CPU不同, 目标程序都没有在cpu上运行, 普通的采样通过在中断处理函数中抓栈的方式就不好用了, 但是我们可以trace内核调度的代码来解决这个问题, 具体做法可以参考 offcputime的源码, 只要trace函数finish_task_switch即可. 对于时钟触发的采样, 开销基本是确定的, 但是对于软件event, 比如scheduler event, 它发生的次数和上面跑的应用执行情况有很强的相关性, 当scheduler event过多的时候, 额外的开销需要注意. 这里也说明熟悉os内核代码对于系统调试来说一定程度上必须的, 一是熟悉内核能够帮助我们理解问题, 二是调试时想了解的很多信息都可以通过内核抓取, 以Brendan的那些工具为例, 很大一部分都是通过在内核插桩完成的.

TSA

Thread State Analysis关注的线程的状态. 当我们说一个请求或者mysql的一条sql执行慢的时候, 它其实是指这个sql的整个延迟, 这包括了执行时间以及等待时间等, 通过拆分出每个状态的时长, 我们就知道该sql是因为cpu执行太长还是io时间太长等.

Scheduler Latency

TSA其实部分覆盖了scheduler latency, 也就是thread处于running但是不能on cpu的状态. 在前公司时升级内核版本的时候有过调试scheduler latency的经验, 现在手上已经没有相关文档, 这里摘取Dick Sites的Datacenter Computers里面的例子. 首先看一下 Dick Sites的介绍, 感受一下名门正宗:

Fred Brooks, John Cocke, and Seymour Cray strongly influenced his approach to computer architecture; Don Knuth his approach to CPU performance; and Edward Tufte his approach to displaying dense tracing information.

这里的方法是通过各种不同的角度观察系统, 并关联到相同的时间轴上:

  • 每个cpu的运行情况. 不只包括idle, kernel, user等状态, 可以包括更精细的event信息
  • 每个请求的运行情况. 和cpu类似, 请求是否在运行, 在运行哪个部分(event)
  • 每个thread的运行情况. 任意时刻thread都在干嘛
  • 每个Lock的情况. 记录lock/unlock的时间, 并且和thread关联起来

有了上面的信息, 我们可以发现当thread被唤醒时, 它并没有马上on cpu, 而是过了50us才得到执行, 这就是调度延迟. 特别地, 这段时间是有cpu处于空闲状态的, 内核调度器从cache的角度决定不做迁移. 在我自己处理的那个case, 及时迁移对性能是有正面影响的. 这不能简单说迁移好还是不迁移好, 所以一般内核会搞个配置选项.

Else

除了以上一些方法外, 还有很多其他方法这里不再一一详述:

  • 日志分析. 这是最基本的, 大部分情况是检查是否有error
  • drill-down. 比如分析文件IO的延迟, 我们先看文件系统层的延迟, 再看io延迟, 如有必要再看scsi命令的处理时间, 层层深入.
  • sampling/tracing. 通用方法.
  • micro-benchmarking.
  • else.

性能分析工具

工具在性能分析过程中作用很大, 熟练使用和编写新的工具都可能加快问题的解决, 但是使用工具或者编写基本的trace工具其实没有太高的门槛, 更高的门槛反而是理解这些工具后面的子系统, 当我们能在这些子系统提出有针对性问题时, 自然就知道需要使用或者编写哪些工具, 所以我把下面的图缩小了.

数据可视化

人终归是视觉动物, 相亲贴说得再好下面的回帖总是无图无真相. 同样的数据不同展示, 起到的效果是完全不一样的, 绝大部分人不能像就电影里面的人那样能一堆跳动的0/1里面能够过滤出有用信息. 一张好的图不仅能帮助我们识别出问题, 还能帮助我们提出问题, 有机会真的有必要学习一下Edward Tufte的大作, 这是门大学问.

Flame Graph

Flame graph现在几乎是性能分析的必备工具, 其流行程度可见一斑, 所以在上面Brendan的75字bio就提到了它. flame graph之所以流行可能有这几个原因:

  • 简单. 一目了然, 几乎不需要任何背景
  • 有效. 栈是调试时极为重要的因素, 抓到栈了基本就清楚了.

现在flame graph几乎做成了图形化显示栈信息的标准方式, 基于frame graph又开发出了differential flame graph, icicle flame graph, offcpu包括wakeup stack的flame graph等.

 

Heat Map

Heat map最核心的思想是用颜色来代表一维, 这样二维的就退化为一维, 三维的退化为二维.

Frequency Trail

和heat map不同, frequency trail并没有降低维度, 而是通过高度来表示frequency, 所以可以有更高的精度. 下面每行表示一个分布, 我们可以很清楚看出每行的分布, 以及圆点代表的outliers. 每座山也可以根据某种规则, 比如mean对齐的方式移动.

性能分析平台

对公司而言, 一套完整的性能分析或者定位平台的重要性不言而喻, 对个人而言也是一样, 没有分析平台的话, 做性能分析就像是打零工, 即使有能力解决各种疑难杂症, 也很难成为那个go-to person, 因为大部分人压根就不知道有这个人, 但是平台却不一样. 将平台作为抓手, 通过平台解决80%-90%的问题, 从而有精力去解决其他的复杂问题. 下面是Netflix的分析流程, 最麻烦的部分也就是Instance Analysis需要用到上述方法. 另外, Atlas的github: .

Dashboard不是将所有的metrics一股脑随意展示出来, 它需要体现出我们定位问题的方法论, 需要便利我们进行调试, 比如使用USE方法应该怎么展示, 使用drill down方法应该怎么展示等等.

引用

与[转帖]读Brendan Gregg - 谈性能分析相似的内容:

[转帖]读Brendan Gregg - 谈性能分析

https://zhuanlan.zhihu.com/p/206743670 Brendan Gregg何许人 Brendan Gregg在性能分析工业界如雷贯耳, 相信看到这篇文章的人肯定知道他的大名. 我们看一下他自己写的bio, 这里摘取的是short版本: Brendan Gregg is

[转帖]读IOPS 640万、写110万:24G SAS/NVMe RAID卡性能谜团

https://aijishu.com/a/1060000000361186 存储 引言:读IOPS__翻倍的原因相对简单,但写IOPS__暴增似乎也是有代价的。MegaRAID 9600__的算法会不会改用纠删码了? 背景阅读 《PCIe 4.0 SAS+NVMe RAID/HBA卡:最高读IOP

[转帖]磁盘读速度巨慢使用arcconf工具调整后的二次优化

情况叙述:lvm文件系统出现损坏,格式为xfs,磁盘修复失败后该节点需要重新格式化处理,格式化后重新划分pv,vg,lv,做完之后应用反应读写的速度达不到应用使用的要求,与正常的相比速度不稳定 现象:time和dd测试速度后发现写的速度为10-20MB/s 解决1:yy3:~ # chmod +x

[转帖]MioIO读/写性能测试

https://www.jianshu.com/p/a0a84f91b16f image.png COSBench是Intel团队基于java开发,是一个测试云对象存储系统的分布式基准测试工具,全称是Cloud Object Storage Benchmark;由Driver和Controller两

[转帖]Innodb存储引擎-锁(数据库锁的查看、快照读&当前读、MVCC、自增长与锁、外键与锁、行锁、并发事务的问题、阻塞、死锁、锁升级、锁的实现)

文章目录 锁lock 与latch读锁/写锁/意向锁INNODB_TRX/INNODB_LOCKS/INNODB_LOCK_WAITS一致性非锁定读(快照读)一致性锁定读(当前读)MVCC版本链Read View流程 自增长与锁外键和锁行锁类型记录锁(record lock)间隙锁(gap lock

[转帖]DBWR与LGWR的写入机制

https://www.jianshu.com/p/6c87cb6cd320 读与写是每个数据库提供的最基本的功能。当数据库中出现第一个进程时,总免不了要将数据从磁盘上加载到内存中,一次数据库的物理I/O由此发生。而这对应着数据库的读事件。通常大多数情况下,数据库中不仅会伴随着大量的读,也会产生大量

[转帖]共识、线性一致性与顺序一致性

https://segmentfault.com/a/1190000022248118 etcd 是线性一致性读,而 zk 却是顺序一致性读,再加上各种共识、强弱一致的名词,看的时候总会混淆,这篇文档就列举下分布式系统中的那些"一致性名词",引用了很多其他的文章,不过会多出一些例子来帮助理解。 什么

[转帖]linux磁盘IO读写性能优化

在LINUX系统中,如果有大量读请求,默认的请求队列或许应付不过来,我们可以 动态调整请求队列数来提高效率,默认的请求队列数存放在/sys/block/xvda/queue/nr_requests 文件中,注意:/sys/block/xvda ,这里 xvda 写的是你自己的硬盘名,因我的是vps所

[转帖]Redis 4.0 自动内存碎片整理(Active Defrag)源码分析

阅读本文前建议先阅读此篇博客: Redis源码从哪里读起 Redis 4.0 版本增加了许多不错的新功能,其中自动内存碎片整理功能 activedefrag 肯定是非常诱人的一个,这让 Redis 集群回收内存碎片相比 Redis 3.0 更加优雅,便利。我们升级 Redis 4.0 后直接开启了a

[转帖]Linux磁盘I/O(二):使用vm.dirty_ratio和vm.dirty_background_ratio优化磁盘性能

文件缓存是一项重要的性能改进,在大多数情况下,读缓存在绝大多数情况下是有益无害的(程序可以直接从RAM中读取数据)。写缓存比较复杂,Linux内核将磁盘写入缓存,过段时间再异步将它们刷新到磁盘。这对加速磁盘I/O有很好的效果,但是当数据未写入磁盘时,丢失数据的可能性会增加。 当然,也存在缓存被写爆的