曹大带我学 Go(12)—— 面向火焰图编程

Posted qcrao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了曹大带我学 Go(12)—— 面向火焰图编程相关的知识,希望对你有一定的参考价值。

你好,我是小X。

曹大最近开 Go 课程了,小X 正在和曹大学 Go。

这个系列会讲一些从课程中学到的让人醍醐灌顶的东西,拨云见日,带你重新认识 Go。

现实中听过各种面向 XX 编程,什么面向过程编程、面向对象编程;也有一些俏皮的,面向薪资编程、面向老板编程;之前曹大还写过一篇,面向事故编程。今天我们来讲讲面向火焰图编程。

一般我们在做性能优化的时候,会先做压测,然后进 pprof 寻找可能的原因及解法。

关注的指标,从服务角度看,包括:

  • 请求量

  • 错误数

  • 延迟

从用户角度看,则是:

  • 延迟(Latency)

  • 吞吐量(Throughput)

性能优化的最终目标就是在延迟可以接受的场景下,尽可能提高系统的吞吐量。

对于 Go 服务,还得看更多:

  • 每秒钟 GC 次数

  • GC 停顿时长(p99, max)

  • GC 占用的 CPU 大小

  • 堆内存占用大小

  • 协程数量

  • 申请、释放的内存大小

  • 申请的对象数

对性能优化而言,我们可以在几个层次分别进行优化:业务层、应用层、底层。

越在上层优化,回报越高。举个简单的例子,有业务方因为历史原因,服务启动之后,会周期性地调我们的接口拿一些数据。但是之后业务发生变动,拿的数据并没有被使用,这块代码也没相应地下线。而且因为对方的集群规模很大,所以这个调用量级还挺大。现在我们服务的容量即将到顶,需要优化服务或者扩容。

如果我们吭哧吭哧地去压测、优化,扩容,很可能也能解决问题。并且,优化做得好的话,也能体现出自己的价值。但是平行世界有另一种解法,那就是去梳理业务方的使用场景,很可能直接就能下掉一半的访问量,收益会大很多,而且操作起来也更简单。

但是,通常情况下可能没这么好运,我们还是得对着火焰图来优化。

火焰图的定义也不复杂:

在 Go 里,一般 pprof web 直接进去的图不太好看懂,我们应该看火焰图 。火焰图就看宽度,宽度越宽,表示占用越大。

不怕它高,就怕它宽。

曹大说,想黑 Go,一张图片就够了:

我在这里有 2 个小点可以分享一下:

  1. pprof 的火焰图用当前这个 bar 的时间除以最上层 bar 的时间,就可以得到某个函数的耗时占比。

  2. 用当前这个 bar 内存使用的占比乘以 RSS,得到的值是我们如果将这一块内存使用优化掉之后,节省的内存大小。

火焰图中的平顶山就很值得优化。什么是平顶山,最终要优化成什么样子?

一句话,山顶很平的 bar 就叫平顶山😅。优化之后,平顶山变窄或消失:

但有尖的是不好优化的 :

最后总结一下,面向火焰图编程,非常简单:我们逮着平顶山优化就行。

现实中可能因为公司的安全部门设置了很多阻碍,我们无法方便地获取 profile 文件,自然就没法愉快地去做性能优化了。基础架构部门要做的事情就是尽可能方便地让研发获取到火焰图。

好了,这就是今天全部的内容了~ 我是小X,我们下期再见~


欢迎关注曹大的 TechPaper 以及码农桃花源~

感谢关注!一线互联网工程师和你一起“精进”职业技能!码农生涯,我们结伴同行~~

希望技术变得有温度!加油~~

目前专注在 Go 语言、后端、性能优化,GTD、效率工具控。开源电子书《Go Questions》已经有 3k star 了。期待交流,一起进步!

以上是关于曹大带我学 Go(12)—— 面向火焰图编程的主要内容,如果未能解决你的问题,请参考以下文章

曹大带我学 Go——调度的本质

『曹大带我学 Go 』系列文章汇总

曹大带我学 Go—— 迷惑的 goroutine 执行顺序

曹大带我学 Go—— 哪里来的 goexit

曹大带我学 Go—— 初识 ast 的威力

曹大带我学 Go—— 一个打点引发的事故