[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介绍几种常用的特征选择方法
特征选择(排序)对于数据科学家.机器学习从业者来说非常重要.好的特征选择能够提升模型的性能,更能帮助我们理解数据的特点.底层结构,这对进一步改善模型.算法都有着重要作用. 特征选择主要有两个功能: 减 ...
随机推荐
- 监听EF执行的sql语句及状态
1.监听EF执行sql的方式 db.Database.Log += c => Console.WriteLine($"sql:{c}"); SQL Server Profil ...
- Ubuntu18.04 GitLab仓库服务器搭建
首先安装必须的一些服务 sudo apt-get update sudo apt-get install -y curl openssh-server ca-certificates sudo apt ...
- MVC4 部署 could not load file or assembly system.web.http.webhost 或是其它文件出误
自从VS2010发布之后使用它来做开发的程序员越来越多,其中很多人使用了MVC来作为新的开发框架,但是在系统部署的时候我们也遇到诸多问题,因为目前大多数windows服务器采用的还是Windows S ...
- node.js开发 1-概述
https://www.cnblogs.com/gaoya666/p/9071288.html Nodejs英文网:https://nodejs.org/en/ 中文网:http://nodejs.c ...
- ios开发之NSData
NSData用于保存字节数组. 初始化 - (instancetype)initWithBytesNoCopy:(void *)bytes length:(NSUInteger)length free ...
- EasyUI DataGrid 根据ID选中行(转载)
转载来源: https://blog.csdn.net/chq00788/article/details/51505519 function selectRows(){ //获取需要选中的记录ID ...
- 使用FastJSON 对Map/JSON/String 进行互转
Fastjson是一个Java语言编写的高性能功能完善的JSON库,由阿里巴巴公司团队开发的主要特性主要体现在以下几个方面: 1.高性能 fastjson采用独创的算法,将parse的速度提升到极致, ...
- 邮件学习过程中关于request.POST的使用
今天的话主要的精力都集中在邮件系统demo的实现,因为自己个人技术有限,所以做出来的相当简陋,在其中碰到的问题其实也是比较多的,对于基于django的邮件相对来说比较容易,然后就是在提交数据,获取po ...
- Java--8--新特性--新的日期API
LocalDate.LocalTime.LocalDateTime 类的实 例是不可变的对象,分别表示使用 ISO-8601日 历系统的日期.时间.日期和时间. Instant 时间戳, 用于“时间戳 ...
- (Linux基础学习)第八章:命令行历史,history
第1节:命令行历史简介保存你输入的命令历史.可以用它来重复执行命令登录shell时,会读取命令历史文件中记录下的命令~/.bash_history登录进shell后新执行的命令只会记录在缓存中:这些命 ...
- golang几种常用配置文件使用方法总结(yaml、toml、json、xml、ini)
- 机器必须闲置。