The website uses cookies. By using this site, you agree to our use of cookies as described in the Privacy Policy.
I Agree
blank_error__heading
blank_error__body
Text direction?

有人说 Go 语言性能不行,大佬不服,使用 pprof 三步优化代码,性能堪比 C++

阅读 4290

这篇文章部分转自:https://www.cnblogs.com/qcrao-2018/p/11832732.html

目录

1,CPU 优化

2,内存优化

3,GC 优化

4,小结

这篇文章讲了一个故事,大意是 Go 语言大佬 Russ Cox 发现一篇文章说使用 Go 写的算法很慢,而 C++ 很快。大佬哪受得了这个,于是使用 Go 语言性能优化神器 pprof,开始了优化实战。最终经过三轮优化,基本上能达到和 C++ 同等的速度和同样的内存消耗。这三轮优化十分具有借签与学习之意义,简述如下:

1,CPU 优化

首先,使用如下代码开启 CPU 监测:

pprof.StartCPUProfile(f)

耗时 top5 的函数,发现一个读 map 的函数耗时最长:mapaccess1_fast64,而它出现在一个递归函数中。执行 web mapaccess1 命令,聚焦出调用 mapaccess1_fast64 函数最多的就是 main.FindLoops 和 main.DFS,再执行命令:list DFS,定位到相关的具体代码。

优化的方法是将 map 改成 slice。当然并不是所有的map都需要这样做,在这个案例中能这样做,和 key 的类型是 int 而且不是太稀疏有关。具体问题需要具体分析,这正是 pprof 工具的价值所在。

修改完之后,再次通过 cpu profiling,发现递归函数 mapaccess1_fast64 的耗时已经不在 top5 中了,但是新增了长耗时函数:runtime.mallocgc,占比 54.2%,而这和内存分配以及垃圾回收相关。

2,内存优化

使用如下代码开启内存监测:

FindHavlakLoops(cfgraph, lsgraph)
f,_ := os.Create(*memprofile)
pprof.WriteHeapProfile(f)

继续通过 top5、list 命令找到内存分配最多的代码位置,发现这回是向 map 里插入元素使用的内存比较多。

改进方式同样是用 slice 代替 map。但 map 有一个缺点,就是可以重复插入元素,因此写一个向 slice 插入元素的函数,可以防止重复插入:

func appendUnique(a []int, x int) []int {
    for _, y := range a {
        if x == y {
            return a
        }
    }
    return append(a, x)
}

好了,现在程序比最初的时候快了 2.1 倍。再次查看 cpu profile 数据,发现 runtime.mallocgc 降了一些,但仍然占比 50.9%。因此需要查看垃圾回收到底在回收哪些内容,这些内容就是导致频繁垃圾回收的“罪魁祸首”。

3,GC 优化

使用 web mallocgc 命令,将和 mallocgc 相关的函数用矢量图的方式展现出来,但是有太多样本量很少的节点影响观察,增加过滤命令:

go tool pprof --nodefraction=0.1 profile

在这条指令中,将少于 10% 的采样点过滤掉。

(注:这是 pprof 生成的分析结果)

新的矢量图可以直观地看出,FindLoops 触发了最多的垃圾回收操作。继续使用命令 list FindLoops 直接找到代码的位置。原来,每次执行 FindLoops 函数时,都要 make 一些临时变量,这会加重垃圾回收器的负担。

改进方式是增加一个全局变量 cache,这样可以重复利用。虽然这样做的坏处是,线程不是安全的了。

4,小结

使用 pprof 工具进行的优化到这就结束了。最后值得提一下,大佬做这件事的时间比较久远,最初写于 2011 年,原文在这里:

https://blog.golang.org/profiling-go-programs

(Russ Cox 优化过程,并附上代码)

原文有更多内容和参考资料,如果有时间推荐查看。

pprof 的包路径是 "runtime/pprof",可以通用报告生成、Web 可视化界面、交互式终端 三种方式来使用。具体使用方法可查相关文档。

本文分享自微信公众号 - 程序员LIYI(CoderLIYI),作者:Stefno

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-11-13

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

Measure
Measure
Related Notes
Get a free MyMarkup account to save this article and view it later on any device.
Create account

End User License Agreement

Summary | 2 Annotations
runtime.mallocgc,占比 54.2%
2020/10/27 09:31
查看垃圾回收到底在回收哪些内容,这些内容就是导致频繁垃圾回收的“罪魁祸首”
2020/10/27 09:35