[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介绍几种常用的特征选择方法
特征选择(排序)对于数据科学家.机器学习从业者来说非常重要.好的特征选择能够提升模型的性能,更能帮助我们理解数据的特点.底层结构,这对进一步改善模型.算法都有着重要作用. 特征选择主要有两个功能: 减 ...
随机推荐
- Matlab M文件变量检测与传递
M文件中变量的检测与传递 可变数量的输入输出变量(varargin,vararout): Matlab的输入输出变量数量可变,并具有以下特点: 可变输入输出变量必须在正常变量之后 varargin和v ...
- Java调用WebService方法总结(9,end)--Http方式调用WebService
Http方式调用WebService,直接发送soap消息到服务端,然后自己解析服务端返回的结果,这种方式比较简单粗暴,也很好用:soap消息可以通过SoapUI来生成,也很方便.文中所使用到的软件版 ...
- 【阿里云开发】- 安装tomcat
Tomcat配置过程 1.下载Tomcat 官网地址:http://tomcat.apache.org/ 这里我用的是apache-tomcat-8.5.38.tar.gz 2.通过ftp工具将下载好 ...
- requests模块 简单使用
目录 requests模块 简单使用 Anaconda简单了解 简单了解 requests模块 使用requests模块 爬取搜狗首页源码数据 实现一个简易的网页采集器 解决乱码问题 解决UA检测问题 ...
- c#使用正则表达式处理字符串
正则表达式可以灵活而高效的处理文本,可以通过匹配快速分析大量的文本找到特定的字符串. 可以验证字符串是否符合某种预定义的格式,可以提取,编辑,替换或删除文本子字符串. 现在如下特定的字符串: stri ...
- 如何在backoffice里创建Hybris image container以及分配给product
登录backoffice,在media container视图点击新建按钮: Catalog选择Product Catalog: 在Properties界面,可以选择media实例放入该contain ...
- SpringBoot 中的使用事务
转自:https://blog.csdn.net/linzhiqiang0316/article/details/52638039 什么是事务? 我们在开发企业应用时,对于业务人员的一个操作实际是对数 ...
- Debian9.5系统安装
1.镜像下载地址 http://cdimage.debian.org/cdimage/archive/ 2.开始安装 如果有配置网络地址,可以手动配置或者跳过等系统安装好后配置. 至此debian9 ...
- consul-服务发现、服务隔离、服务配置
一.服务发现 服务发现组件记录了(大规模)分布式系统中所有服务的信息,其它服务可以据此找到这些服务.DNS 就是一个简单的例子.当然,复杂系统的服务发现组件要提供更多的功能,例如,服务元数据存储.健康 ...
- SpringCloud_Eureka与Zookeeper对比
关系型数据库与非关系型数据库及其特性: RDBMS(Relational Database Management System 关系型数据库) :mysql/oracle/sqlServer等 = ...
- golang几种常用配置文件使用方法总结(yaml、toml、json、xml、ini)
- 机器必须闲置。