[golang]7种 Go 程序性能分析方法
视频信息
Seven ways to Profile Go Applications
by Dave Cheney
at Golang UK Conf. 2016
- 视频:https://www.youtube.com/watch?v=2h_NFBFrciI
- 幻灯:http://talks.godoc.org/github.com/davecheney/presentations/seven.slide#1
方法一:time
shell 内置的 time
最简单的性能测试工具就是 shell 中内置的 time 命令,这是由 POSIX.2 (IEEE Std 1003.2-1992) 标准定义的,因此所有 Unix/Linux 都有这个内置命令。
|
$ time go fmt github.com/docker/machine
real 0m0.110s
user 0m0.056s
sys 0m0.040s
|
这是使用shell内置的 time来对 go fmt github.com/docker/machine 的命令进行性能分析。
这里一共有3项指标:
real:从程序开始到结束,实际度过的时间;user:程序在用户态度过的时间;sys:程序在内核态度过的时间。
一般情况下 real >= user + sys,因为系统还有其它进程。
GNU 实现的 time
除此以外,对于 Linux 系统,还有一套 GNU 的 time,位于 /usr/bin/time,需要用完整路径去调用,不过这个功能就更强大了。
|
vagrant@vagrant:~$ /usr/bin/time -v go fmt github.com/docker/machine
Command being timed: "go fmt github.com/docker/machine"
User time (seconds): 0.02
System time (seconds): 0.06
Percent of CPU this job got: 85%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.09
Average shared text size (kbytes): 0
Average unshared data size (kbytes): 0
Average stack size (kbytes): 0
Average total size (kbytes): 0
Maximum resident set size (kbytes): 18556
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 0
Minor (reclaiming a frame) page faults: 9925
Voluntary context switches: 430
Involuntary context switches: 121
Swaps: 0
File system inputs: 0
File system outputs: 32
Socket messages sent: 0
Socket messages received: 0
Signals delivered: 0
Page size (bytes): 4096
Exit status: 0
|
可以看到这里的功能要强大多了,除了之前的信息外,还包括了:
- CPU占用率;
- 内存使用情况;
- Page Fault 情况;
- 进程切换情况;
- 文件系统IO;
- Socket 使用情况;
- ……
*BSD、macOS 的 time
*BSD 也有自己实现的 time,功能稍逊,但也比 Shell 里的 time 强大。比如 macOS 中继承自 FreeBSD 的 time:
|
$ /usr/bin/time -l go fmt github.com/docker/machine
0.70 real 0.05 user 0.40 sys
11710464 maximum resident set size
0 average shared memory size
0 average unshared data size
0 average unshared stack size
8579 page reclaims
2571 page faults
0 swaps
0 block input operations
0 block output operations
0 messages sent
0 messages received
3 signals received
1118 voluntary context switches
1702 involuntary context switches
$
|
这里有:
- 内存使用情况
- Page Fault 情况
- IO 情况
- 进程切换情况
- Signal 情况
- ……
go tool 中的 -toolexec 参数
当我们构建很慢的时候,如何才能知道为什么慢呢?go 工具链中支持 -x 命令,可以显示具体执行的每一条命令,这样我们就可以看到到底执行到哪里的时候慢了。
|
$ go build -x fmt
WORK=/var/folders/wc/9tzsn1hd7c38tvc54kctn4100000gn/T/go-build846067626
mkdir -p $WORK/runtime/internal/sys/_obj/
mkdir -p $WORK/runtime/internal/
cd /usr/local/Cellar/go/1.9.1/libexec/src/runtime/internal/sys
/usr/local/Cellar/go/1.9.1/libexec/pkg/tool/darwin_amd64/compile -o $WORK/runtime/internal/sys.a -trimpath $WORK -goversion go1.9.1 -p runtime/internal/sys -std -+ -complete -buildid 2749cc50ea3a4ebcf
...
|
但是如果构建时间很长,或者是计划在 CI 中运行,我们就不可能一直盯着了。当然,我们可以时候从输出中复制粘贴到命令行,前缀上 time,也可以知道每个命令的执行时间。不过这太繁琐了。
go tool 工具链中,还支持一个叫做 -toolexec 的参数,其值将作为工具链每一个命令的前缀来执行。
|
go build -toolexec=... github.com/pkg/profile
go test -toolexec=... net/http
...
|
换句话说,如果 -toolexec=time,那么假如有一个 go build xxx.go 的命令,就会变为 time go build xxx.go 来执行。
|
$ go build -toolexec="/usr/bin/time" cmd/compile/internal/gc
# runtime/internal/sys
0.09 real 0.01 user 0.02 sys
# runtime/internal/atomic
0.01 real 0.00 user 0.00 sys
# runtime/internal/atomic
0.02 real 0.00 user 0.00 sys
# runtime
1.60 real 1.90 user 0.12 sys
# runtime
0.00 real 0.00 user 0.00 sys
# runtime
0.02 real 0.01 user 0.00 sys
# runtime
0.01 real 0.00 user 0.00 sys
# runtime
0.00 real 0.00 user 0.00 sys
...
|
用好了,这就可以变得很强大,不仅仅是计时。比如,我们 go build 的时候我们可以在 Mac 或者 Linux 上进行交叉编译,但是 go test 的时候,我们希望则在手机设备上直接运行。另外,也可以用来校验输出结果的一致性 (toolstash)
方法二:GODEBUG
/usr/bin/time 是外部工具,除此外,我们还可以使用 Go 内置的功能。Go 的 runtime 可以收集程序运行周期内的很多数据。当然,这些收集默认都是不启用的,你可以手动启用特定信息的收集。
比如,如果你关心垃圾收集,则可以启用 gctrace=1 标志。如:
|
$ env GODEBUG=gctrace=1 godoc -http=:8080
gc 1 @18446741350.644s 0%: 0.026+2.0+0.075 ms clock, 0.052+2.6/2.0/0+0.15 ms cpu, 4->4->0 MB, 5 MB goal, 4 P
gc 2 @18446741350.664s 0%: 0.12+1.5+0.049 ms clock, 0.25+0.50/1.2/0+0.098 ms cpu, 4->4->1 MB, 5 MB goal, 4 P
gc 3 @18446741350.695s 0%: 0.024+1.1+0.059 ms clock, 0.072+1.3/0.96/0+0.17 ms cpu, 4->4->1 MB, 5 MB goal, 4P
gc 4 @18446741350.714s 0%: 0.036+1.8+0.092 ms clock, 0.11+1.4/1.7/0+0.27 ms cpu, 4->4->1 MB, 5 MB goal, 4 P
gc 5 @18446741350.746s 0%: 0.021+2.2+0.055 ms clock, 0.087+2.5/2.1/0+0.22 ms cpu, 4->4->1 MB, 5 MB goal, 4 P
gc 6 @18446741350.770s 0%: 0.013+4.5+0.12 ms clock, 0.053+1.3/3.9/0+0.50 ms cpu, 4->4->1 MB, 5 MB goal, 4 P
gc 7 @18446741350.800s 0%: 0.020+2.5+0.056 ms clock, 0.083+2.4/2.5/0+0.22 ms cpu, 4->4->2 MB, 5 MB goal, 4 P
gc 8 @18446741350.817s 0%: 0.030+3.2+0.053 ms clock, 0.12+2.8/3.0/0+0.21 ms cpu, 4->4->2 MB, 5 MB goal, 4 P
gc 9 @18446741350.845s 0%: 0.041+4.7+0.10 ms clock, 0.16+1.6/4.3/0+0.40 ms cpu, 4->4->2 MB, 5 MB goal, 4 P
gc 10 @18446741350.881s 0%: 0.018+3.7+0.070 ms clock, 0.072+2.5/3.6/0+0.28 ms cpu, 4->4->2 MB, 5 MB goal, 4
...
|
这样的话,垃圾收集的信息都会被输出出来,可以帮助 GC 排障。如果发现 GC 一直都在很忙碌的工作,那恐怕内存管理上有可以改进的地方。
插曲一:Profiler 是如何工作的?
Profiler 会启动你的程序,然后通过配置操作系统,来定期中断程序,然后进行采样。比如发送 SIGPROF 信号给被分析的进程,这样进程就会被暂停,然后切换到 Profiler 中进行分析。Profiler 则取得被分析的程序的每个线程的当前位置等信息进行统计,然后恢复程序继续执行。
性能分析注意事项
- 性能分析必须在一个可重复的、稳定的环境中来进行。
- 机器必须闲置。
- 不要在共享硬件上进行性能分析;
- 不要在性能分析期间,在同一个机器上去浏览网页!!
[golang]7种 Go 程序性能分析方法的更多相关文章
- golang几种常用配置文件使用方法总结(yaml、toml、json、xml、ini)
原文连接: https://blog.csdn.net/wade3015/article/details/83351776 yaml配置文件的使用方法总结 首先介绍使用yaml配置文件,这里使用的是g ...
- Golang程序性能分析
前言 程序性能分析我相信是每个程序员都会遇到的问题,比如说一个程序的CPU为什么占用这么高?有没有优化的空间?又比如程序出现了内存泄漏如何排查等等.如果是C++程序会借助于Google pprof c ...
- 八、jdk工具之JvisualVM、JvisualVM之二--Java程序性能分析工具Java VisualVM
目录 一.jdk工具之jps(JVM Process Status Tools)命令使用 二.jdk命令之javah命令(C Header and Stub File Generator) 三.jdk ...
- javascript四种类型识别的方法
× 目录 [1]typeof [2]instanceof [3]constructor[4]toString 前面的话 javascript有复杂的类型系统,类型识别则是基本的功能.javascrip ...
- Linux下的应用程序性能分析 总结
Linux下的应用程序性能分析,根据内核程序和应用程序的不同,下文分两类进行描述. 我们侧重的是应用级别的程序,推荐google perf tool/kcachegrind组合 一.和内核有关的工具 ...
- iOS 三种收起键盘的方法
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typica ...
- 干货:结合Scikit-learn介绍几种常用的特征选择方法
原文 http://dataunion.org/14072.html 主题 特征选择 scikit-learn 作者: Edwin Jarvis 特征选择(排序)对于数据科学家.机器学习从业者来说非 ...
- 【读书笔记】iOS-开发技巧-三种收起键盘的方法
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typica ...
- 结合Scikit-learn介绍几种常用的特征选择方法
特征选择(排序)对于数据科学家.机器学习从业者来说非常重要.好的特征选择能够提升模型的性能,更能帮助我们理解数据的特点.底层结构,这对进一步改善模型.算法都有着重要作用. 特征选择主要有两个功能: 减 ...
随机推荐
- jdk安装以及Java环境配置
jdk其实自己大一的时候就已经装过,java环境也配置过,但是随着后面学习的东西越来越多,要安装的软件也越来越多,一开始没有安装路径的概念,好多东西都放的很乱.接着这次自己复习java的机会,于是重新 ...
- js --装饰者模式
定义 装饰者模式能够在补改变对象自身的基础上,在程序运行期间给对象动态的添加职责. 当看到装饰者模式的定义的时候,我们想到的js 的三大特性之一--继承,不也能够实现不改变对象自身的基础上,添加动态的 ...
- fastDFS遇到的并发问题recv cmd: 0 is not correct, expect cmd: 100
这种异常一般发生在 多线程同时使用一个StorageClient操作文件的情况下.有两种解决办法:1.对StorageClient对象加锁,变成单线程2.每次下载或上传文件时,重新new一个Stora ...
- chrome滚动条颜色尺寸设置
<style> /*chrome滚动条颜色设置*/ *::-webkit-scrollbar { width: 5px; height: 10px; background-color: t ...
- Java System Reports
You use Java System Reports as a problem detection and analysis tool to: ● Monitor the AS Java ...
- oracle rpad()和lpad()函数
函数参数:rpad( string1, padded_length, [ pad_string ] ) rpad函数从右边对字符串使用指定的字符进行填充 string 表示:被填充的字符串 padde ...
- python之PEP8规范
比较需要注意的 缩进 每一级缩进使用4个空格. 续行应该与其包裹元素对齐,要么使用圆括号.方括号和花括号内的隐式行连接来垂直对齐,要么使用挂行缩进对齐3.当使用挂行缩进时,应该考虑到第一行不应该有参数 ...
- FastJSON JSONObject 字段排序 Feature.OrderedField
package cn.tongdun.robot.web; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.TypeRefe ...
- 小程序框架之视图层 View~基础组件
框架为开发者提供了一系列基础组件,开发者可以通过组合这些基础组件进行快速开发.详细介绍请参考组件文档. 什么是组件: 组件是视图层的基本组成单元. 组件自带一些功能与微信风格一致的样式. 一个组件通常 ...
- keras模块之-优化器(optimizers)--笔记
本笔记由博客园-圆柱模板 博主整理笔记发布,转载需注明,谢谢合作! 优化器是调整每个节点权重的方法,如: model = Sequential() model.add(Dense(64, init=' ...
- golang几种常用配置文件使用方法总结(yaml、toml、json、xml、ini)
- 机器必须闲置。