[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介绍几种常用的特征选择方法
特征选择(排序)对于数据科学家.机器学习从业者来说非常重要.好的特征选择能够提升模型的性能,更能帮助我们理解数据的特点.底层结构,这对进一步改善模型.算法都有着重要作用. 特征选择主要有两个功能: 减 ...
随机推荐
- Linux用户管理的基本概念
Linux系统如何区别不同的用户呢?可以很自然地想到,使用不同的用户名应该是一个好主意,就像真实世界中每个人都有名字一样.但“用户名”只是一种方便让人读的字符串,对机器来说是没有意义的.事实上,Lin ...
- Linux中shell字符串分隔、字符串替换、字符串拼接
1.从properties文件中读取变量 SERVER_NAME=`sed '/project.config/!d;s/.*=//' conf/dubbo.properties | tr -d '\r ...
- springboot超级详细的日志配置(基于logback)
前言 java web 下有好几种日志框架,比如:logback,log4j,log4j2(slj4f 并不是一种日志框架,它相当于定义了规范,实现了这个规范的日志框架就能够用 slj4f 调用) ...
- Django:必会ORM查
1.ORM常用字段 在models.py,创建表中字段 1.1AutoField 自增的整形字段,必填参数primary_key=True,则成为数据库的主键.无该字段时,django自动创建.一个m ...
- Android 低功耗蓝牙BLE 开发注意事项
基本概念和问题 1.蓝牙设计范式? 当手机通过扫描低功耗蓝牙设备并连接上后,手机与蓝牙设备构成了客户端-服务端架构.手机通过连接蓝牙设备,可以读取蓝牙设备上的信息.手机就是客户端,蓝牙设备是服务端. ...
- AI人脸识别SDK接入 — 参数优化篇(虹软)
引言 使用了虹软公司免费的人脸识别算法,感觉还是很不错的,当然,如果是初次接触的话会对一些接口的参数有些疑问的.这里分享一下我对一些参数的验证结果(这里以windows版本为例,linux.andro ...
- with读、写文件
1.with写文件 save_file = "1.txt" str_data = "123a\nbc" with open(save_file, 'a', en ...
- Elasticsearch 术语介绍和CRUD实际操作入门
一.Elastic Stack 核心Elasticsearch Elasticsearch 是一个分布式.RESTful 风格的搜索和数据分析引擎.Elasticsearch 是面向文档的,这就意味着 ...
- 深度学习 吴恩达深度学习课程2第三周 tensorflow实践 参数初始化的影响
博主 撸的 该节 代码 地址 :https://github.com/LemonTree1994/machine-learning/blob/master/%E5%90%B4%E6%81%A9%E8 ...
- 使用AutoIt实现文件上传
在网页上上传文件的时候,Selenium无法直接操作如Flash.JavaScript 或Ajax 等技术所实现的上传功能,这时候我们需要借用一个叫做AutoIt的软件来帮助我们事先自动化的上传操作. ...
- golang几种常用配置文件使用方法总结(yaml、toml、json、xml、ini)
- 机器必须闲置。