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统计的, 我们也可以通过采样的方法生成火焰图. http://www.brendangregg.com/blog/2014-10-31/cpi-flame-graphs.html. 典型的场景比如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: https://github.com/Netflix/atlas.

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

引用

[转帖]读Brendan Gregg - 谈性能分析的更多相关文章

  1. 浅谈java性能分析

    浅谈java性能分析,效能分析 在老师强烈的要求下做了效能分析,对上次写过的词频统计的程序进行分析以及改进. 对于效能分析:我个人很浅显的认为就是程序的运行效率,代码的执行效率等等. java做性能测 ...

  2. 浅谈Unity的渲染优化(1): 性能分析和瓶颈判断(上篇)

    http://www.taidous.com/article-667-1.html 前言 首先,这个系列文章做个大致的介绍,题目"浅谈Unity",因为公司和国内大部分3D手游开发 ...

  3. Linux 性能分析工具汇总合集

    出于对Linux操作系统的兴趣,以及对底层知识的强烈欲望,因此整理了这篇文章.本文也可以作为检验基础知识的指标,另外文章涵盖了一个系统的方方面面.如果没有完善的计算机系统知识,网络知识和操作系统知识, ...

  4. Linux性能分析的前60000毫秒【转】

    Linux性能分析的前60000毫秒 为了解决性能问题,你登入了一台Linux服务器,在最开始的一分钟内需要查看什么? 在Netflix我们有一个庞大的EC2 Linux集群,还有非常多的性能分析工具 ...

  5. [转]Linux性能分析工具汇总合集

    出于对Linux操作系统的兴趣,以及对底层知识的强烈欲望,因此整理了这篇文章.本文也可以作为检验基础知识的指标,另外文章涵盖了一个系统的方方面面.如果没有完善的计算机系统知识,网络知识和操作系统知识, ...

  6. 超全整理!Linux性能分析工具汇总合集

    转自:http://rdc.hundsun.com/portal/article/731.html?ref=myread 出于对Linux操作系统的兴趣,以及对底层知识的强烈欲望,因此整理了这篇文章. ...

  7. Linux 性能分析的前 60 秒

    编译自:http://techblog.netflix.com/2015/11/linux-performance-analysis-in-60s.html作者: Brendan Gregg转载自:h ...

  8. (转)超全整理!Linux性能分析工具汇总合集

    超全整理!Linux性能分析工具汇总合集 原文:http://rdc.hundsun.com/portal/article/731.html 出于对Linux操作系统的兴趣,以及对底层知识的强烈欲望, ...

  9. Linux性能分析命令工具汇总

    转自:http://rdc.hundsun.com/portal/article/731.html?ref=myread 出于对Linux操作系统的兴趣,以及对底层知识的强烈欲望,因此整理了这篇文章. ...

  10. SQL2005性能分析一些细节功能你是否有用到?

    原文:SQL2005性能分析一些细节功能你是否有用到? 我相信很多朋友对现在越来越大的数据量而感到苦恼,可是总要面对现实啊,包括本人在内的数据库菜鸟们在开发B/S程序时,往往只会关心自己的数据是否正确 ...

随机推荐

  1. antd ui的from使用问题

    select 的allowClear失效问题 select的value与allowClear同时使用会导致allowClear失效 解决方法 from包装一层,通过const [form] = For ...

  2. 揭秘华为云GaussDB(for Redis)丨大key治理

    本文分享自华为云社区<华为云GaussDB(for Redis)揭秘第31期:大key治理>,作者: 高斯Redis官方博客. 从DBA的视角看,大Key无疑是引起Redis线上问题的常见 ...

  3. 问鼎CodeXGLUE榜单,华为云UniXcoder-VESO-v1算法取得突破

    摘要:华为云PaaS技术创新团队基于UniXcoder模型,在公开测试数据集(CodeXGLUE)上的代码搜索任务评测结果上取得突破,在CodeXGLUE榜单上排名中第一. 本文分享自华为云社区< ...

  4. 初学开发必看:何为Git,何为SVN

    摘要:在和客户交流代码开发的过程中,时常会先入为主的交流起Git:但在和很多中小型企业交流的过程,发现SVN的模式也被使用得很频繁.那么两者的具体差异有哪些呢? 本文分享自华为云社区<Git V ...

  5. vue2升级vue3:vue3真的需要vuex或者Pinia吗?hooks全有了

    在写 <vue2升级vue3:TypeScript下vuex-module-decorators/vuex-class to vuex4.x>,建议新项目使用 Pinia,但是我的项目部分 ...

  6. 高性能 Jsonpath 框架,Snack3 3.2.54 发布(支持 kotlin data 类反序化)

    Snack3,一个高性能的 JsonPath 框架 借鉴了 Javascript 所有变量由 var 申明,及 Xml dom 一切都是 Node 的设计.其下一切数据都以ONode表示,ONode也 ...

  7. Kubernetes(K8S) helm 安装

    Helm 是一个 Kubernetes 的包管理工具, 就像 Linux 下的包管理器, 如 yum/apt 等, 可以很方便的将之前打包好的 yaml 文件部署到 kubernetes 上. Hel ...

  8. JDk 与 ADB 环境变量配置

    ### Java环境变量配置 首先,JDK是整个Java的核心,包括了Java运行环境,一推Java工具和Java基础的类库. 网址:https://www.oracle.com/technetwor ...

  9. DNS--安装&&配置文件

    1 下载 #下载服务yum -y install bind#下载解析工具yum -y install bind-utils 2 配置文件 主配置文件 /etc/named.conf 区配置文件 /va ...

  10. 什么是「滑动窗口算法」(sliding window algorithm),有哪些应用场景?

    今天是算法数据结构专题的第2篇文章,我们一起来学习一下「滑动窗口算法」. 前言 最近刷到leetCode里面的一道算法题,里面有涉及到Sliding windowing算法,因此写一篇文章稍微总结一下 ...