专栏名称: SegmentFault思否
SegmentFault (www.sf.gg)开发者社区,是中国年轻开发者喜爱的极客社区,我们为开发者提供最纯粹的技术交流和分享平台。
目录
相关文章推荐
OSC开源社区  ·  Bun ... ·  22 小时前  
OSC开源社区  ·  RAG市场的2024:随需而变,从狂热到理性 ·  22 小时前  
码农翻身  ·  漫画 | 为什么大家都愿意进入外企? ·  昨天  
程序员的那些事  ·  OpenAI ... ·  昨天  
程序员小灰  ·  3个令人惊艳的DeepSeek项目,诞生了! ·  2 天前  
51好读  ›  专栏  ›  SegmentFault思否

Golang 大杀器之性能剖析 PProf

SegmentFault思否  · 公众号  · 程序员  · 2018-09-25 08:00

正文

前言

写了几吨代码,实现了几百个接口。功能测试也通过了,终于成功的部署上线了。

结果,性能不佳,什么鬼?😭

想做性能分析

PProf

想要进行性能优化,首先瞩目在 Go 自身提供的工具链来作为分析依据,本文将带你学习、使用 Go 后花园,涉及如下:

  • runtime/pprof:采集程序(非 Server)的运行数据进行分析

  • net/http/pprof:采集 HTTP Server 的运行时数据进行分析

是什么

pprof 是用于可视化和分析性能分析数据的工具。

pprof 以 profile.proto 读取分析样本的集合,并生成报告以可视化并帮助分析数据(支持文本和图形报告)。

profile.proto 是一个 Protocol Buffer v3 的描述文件,它描述了一组 callstack 和 symbolization 信息, 作用是表示统计分析的一组采样的调用栈,是很常见的 stacktrace 配置文件格式。

支持什么使用模式
  • Report generation:报告生成

  • Interactive terminal use:交互式终端使用

  • Web interface:Web 界面

可以做什么
  • CPU Profiling:CPU 分析,按照一定的频率采集所监听的应用程序 CPU(含寄存器)的使用情况,可确定应用程序在主动消耗 CPU 周期时花费时间的位置

  • Memory Profiling:内存分析,在应用程序进行堆分配时记录堆栈跟踪,用于监视当前和历史内存使用情况,以及检查内存泄漏

  • Block Profiling:阻塞分析,记录 goroutine 阻塞等待同步(包括定时器通道)的位置

  • Mutex Profiling:互斥锁分析,报告互斥锁的竞争情况

一个简单的例子

我们将编写一个简单且有点问题的例子,用于基本的程序初步分析。

编写 demo 文件

(1)demo.go,文件内容:

  1. package main

  2. import (

  3.    "log"

  4.    "net/http"

  5.    _ "net/http/pprof"

  6.    "github.com/EDDYCJY/go-pprof-example/data"

  7. )

  8. func main() {

  9.    go func() {

  10.        for {

  11.            log.Println(data.Add("https://github.com/EDDYCJY"))

  12.        }

  13.    }()

  14.    http.ListenAndServe("0.0.0.0:6060", nil)

  15. }

(2)data/d.go,文件内容:

  1. package data

  2. var datas []string

  3. func Add(str string) string {

  4.    data := []byte(str)

  5.    sData := string(data)

  6.    datas = append(datas, sData)

  7.    return sData

  8. }

运行这个文件,你的 HTTP 服务会多出 /debug/pprof 的 endpoint 可用于观察应用程序的情况。

分析

一、通过 Web 界面

查看当前总览:访问 http : //127.0.0.1:6060/debug/pprof/

  1. /debug/pprof/

  2. profiles:

  3. 0    block

  4. 5    goroutine

  5. 3    heap

  6. 0    mutex

  7. 9    threadcreate

  8. full goroutine stack dump

这个页面中有许多子页面,咱们继续深究下去,看看可以得到什么?

  • cpu(CPU Profiling): $HOST / debug / pprof / profile ,默认进行 30s 的 CPU Profiling,得到一个分析用的 profile 文件

  • block(Block Profiling): $HOST / debug / pprof / block ,查看导致阻塞同步的堆栈跟踪

  • goroutine: $HOST / debug / pprof / goroutine ,查看当前所有运行的 goroutines 堆栈跟踪

  • heap(Memory Profiling): $HOST / debug / pprof / heap ,查看活动对象的内存分配情况

  • mutex(Mutex Profiling): $HOST / debug / pprof / mutex ,查看导致互斥锁的竞争持有者的堆栈跟踪

  • threadcreate: $HOST / debug / pprof / threadcreate ,查看创建新OS线程的堆栈跟踪

二、通过交互式终端使用

(1)go tool pprof http://localhost:6060/debug/pprof/profile?seconds=60

  1. $ go tool pprof http://localhost:6060/debug/pprof/profile\?seconds\=60

  2. Fetching profile over HTTP from http://localhost:6060/debug/pprof/profile?seconds=60

  3. Saved profile in /Users/eddycjy/pprof/pprof.samples.cpu.007.pb.gz

  4. Type: cpu

  5. Duration: 1mins, Total samples = 26.55s (44.15%)

  6. Entering interactive mode (type "help" for commands, "o" for options)

  7. (pprof)

执行该命令后,需等待 60 秒(可调整 seconds 的值),pprof 会进行 CPU Profiling。结束后将默认进入 pprof 的交互式命令模式,可以对分析的结果进行查看或导出。具体可执行 pprof help 查看命令说明。

  1. (pprof) top10

  2. Showing nodes accounting for 25.92s, 97.63% of 26.55s total

  3. Dropped 85 nodes (cum <= 0.13s)

  4. Showing top 10 nodes out of 21

  5.      flat  flat%   sum%        cum   cum%

  6.    23.28s 87.68% 87.68%     23.29s 87.72%  syscall.Syscall

  7.     0.77s  2.90% 90.58%      0.77s  2.90%  runtime.memmove

  8.     0.58s  2.18% 92.77%      0.58s  2.18%  runtime.freedefer

  9.     0.53s  2.00% 94.76%      1.42s  5.35%  runtime.scanobject

  10.     0.36s  1.36% 96.12%      0.39s  1.47%  runtime.heapBitsForObject

  11.     0.35s  1.32% 97.44%      0.45s  1.69%  runtime.greyobject

  12.     0.02s 0.075% 97.51%     24.96s 94.01%  main.main.func1

  13.     0.01s 0.038% 97.55%     23.91s 90.06%  os.(*File).Write

  14.     0.01s 0.038% 97.59%      0.19s  0.72%  runtime.mallocgc

  15.     0.01s 0.038% 97.63%     23.30s 87.76%  syscall.Write

说明:

  • flat:给定函数上运行耗时

  • flat%:同上的 CPU 运行耗时总比例

  • sum%:给定函数累积使用 CPU 总比例

  • cum:当前函数加上它之上的调用运行总耗时

  • cum%:同上的 CPU 运行耗时总比例

最后一列为函数名称,在大多数的情况下,我们可以通过这五列得出一个应用程序的运行情况,加以优化 🤔。

(2)go tool pprof http://localhost:6060/debug/pprof/heap

  1. $ go tool pprof http://localhost:6060/debug/pprof/heap

  2. Fetching profile over HTTP from http://localhost:6060/debug/pprof/heap

  3. Saved profile in /Users/eddycjy/pprof/pprof.alloc_objects.alloc_space.inuse_objects.inuse_space.008.pb.gz

  4. Type: inuse_space

  5. Entering interactive mode (type "help" for commands, "o" for options)

  6. (pprof) top

  7. Showing nodes accounting for 837.48MB, 100% of 837.48MB total

  8.      flat  flat%   sum%        cum   cum%

  9.  837.48MB   100%   100%   837.48MB   100%  main.main.func1

说明:

  • -inuse_space:分析应用程序的常驻内存占用情况

  • -alloc_objects:分析应用程序的内存临时分配情况

(3) go tool pprof http://localhost:6060/debug/pprof/block

(4) go tool pprof http://localhost:6060/debug/pprof/mutex

三、PProf 可视化界面

这是令人期待的一小节。在这之前,我们需要简单的编写好测试用例来跑一下。

编写测试用例:

(1)新建 data/d_test.go,文件内容:

  1. package data

  2. import "testing"

  3. const url = "https://github.com/EDDYCJY"

  4. func TestAdd(t *testing.T)







请到「今天看啥」查看全文