Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

第 83 期对 Go 程序进行可靠的性能测试 #564

Closed
changkun opened this issue Mar 3, 2020 · 11 comments
Closed

第 83 期对 Go 程序进行可靠的性能测试 #564

changkun opened this issue Mar 3, 2020 · 11 comments
Assignees
Labels
Go 夜读 Go 夜读:主题分享 工程实践与架构设计 Go 夜读分享主题:一些工程实践,架构设计等的经验总结分享 已分享 ✅ Go 夜读的分享状态:分享已完成。

Comments

@changkun
Copy link
Member

changkun commented Mar 3, 2020

【Go 夜读】 对 Go 程序进行可靠的性能测试

性能测试是 Go 语言工具链中比较重要的一环。我们已经知道了如何编写一个形如 func BenchmarkFunc(b *testing.B) 形式的的性能测试。那他的目标是什么?是否对其进行独立运行就已经足够了?如果不是,那如何才能正确的进行性能测试?又如何判断我们性能测试得到的结果是可靠的?

benchstat 作为 Go 语言工具链的一环,为我们提供了进行可靠性能测试的必要条件之一。那么 benchstat 又是什么?benchstat 能够为我们做哪些事情?它的基本原理又是什么?有了 benchstat 之后我们就可以「高枕无忧」了吗?我们还需要什么其他的工具吗?

本次分享我们将就上述这些问题展开,讨论如何在 Go 语言中进行可靠的性能测试。

大纲

  • 准备可靠的测试环境
  • benchstat
  • 例子与实践
    • 对代码块进行性能调优
    • Benchmark 的正确性分析
    • 其他的影响因素
  • benchstat 中假设检验的原理
  • 局限性及应对措施

分享者自我介绍

Go 夜读 SIG 小组

分享时间

2020-03-26 21:00 UTC+8

分享地址

https://zoom.us/j/6923842137

Slides

https://changkun.de/s/gobench/

参考资料


Q&A

在分享结束后提供。

@changkun changkun added Go 夜读 Go 夜读:主题分享 工程实践与架构设计 Go 夜读分享主题:一些工程实践,架构设计等的经验总结分享 已排期 🗓️ Go 夜读的分享状态:已确定分享时间。 labels Mar 3, 2020
@changkun changkun self-assigned this Mar 3, 2020
@changkun changkun changed the title 第 81 期 benchstat: 对 Go 程序进行可靠的性能测试 第 81 期 对 Go 程序进行可靠的性能测试 Mar 6, 2020
@yangwenmai yangwenmai pinned this issue Mar 12, 2020
@yangwenmai yangwenmai changed the title 第 81 期 对 Go 程序进行可靠的性能测试 第 82 期 对 Go 程序进行可靠的性能测试 Mar 13, 2020
@junyicc
Copy link

junyicc commented Mar 17, 2020

延伸一下,可否顺带分享关于如何观察和调优程序的性能?在工程中如何正确使用pprof等工具,在生产环境中有哪些注意事项等?

@changkun
Copy link
Member Author

延伸一下,可否顺带分享关于如何观察和调优程序的性能?在工程中如何正确使用pprof等工具,在生产环境中有哪些注意事项等?

这次分享的内容其实有些多,再延伸这些主题时间就太长了,如果你感兴趣可以提 issue 来发起投票,例如 #566

@yangwenmai yangwenmai changed the title 第 82 期 对 Go 程序进行可靠的性能测试 第 83 期对 Go 程序进行可靠的性能测试 Mar 24, 2020
@luojiego
Copy link
Contributor

微信图片_20200325235204

  1. benchmark两个函数的对比 执行的总时间是否相等?2. 在对比性能的时候,是否需要测试机器要绝对的干净?

@changkun
Copy link
Member Author

微信图片_20200325235204

  1. benchmark两个函数的对比 执行的总时间是否相等?2. 在对比性能的时候,是否需要测试机器要绝对的干净?

分享的时候会覆盖这些问题。

@luojiego
Copy link
Contributor

微信图片_20200325235204

  1. benchmark两个函数的对比 执行的总时间是否相等?2. 在对比性能的时候,是否需要测试机器要绝对的干净?

分享的时候会覆盖这些问题。

感谢欧神的秒回,还在追你之前的分享……

@changkun
Copy link
Member Author

@l7l1l0l 可以把你的测试代码分享出来,到时候 QA 可以拿来做个例子来讲

@luojiego
Copy link
Contributor

@l7l1l0l 可以把你的测试代码分享出来,到时候 QA 可以拿来做个例子来讲

ok 明天早上我补充上来

@luojiego
Copy link
Contributor

整数转换

代码

package convert_test

import (
	"fmt"
	"strconv"
	"testing"
)

var (
	i int64 = 1
)

func ConvertBySPrintf() {
	fmt.Sprintf("%d", i)
}

func ConvectByFormatInt() {
	strconv.FormatInt(i, 10)
}

func BenchmarkSprintf(b *testing.B) {
	for i := 0; i < b.N; i++ {
		ConvertBySPrintf()
	}
}

func BenchmarkStrConv(b *testing.B) {
	for i := 0; i < b.N; i++ {
		ConvectByFormatInt()
	}
}

结果

goos: linux
goarch: amd64
BenchmarkSprintf-4   	12112816	        87.9 ns/op	       8 B/op	       1 allocs/op
BenchmarkStrConv-4   	352274472	         3.43 ns/op	       0 B/op	       0 allocs/op
PASS
ok  	command-line-arguments	2.737s

@luojiego
Copy link
Contributor

字符串拼接

s1 = s1 + s2

代码

//string_test.go
package string_test

import (
	"fmt"
	"testing"
)

func Benchmark1(b *testing.B) {
	s1 := "hello"
	s2 := "world"
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		s1 = fmt.Sprintf("%s %s", s1, s2)
	}
}

func Benchmark2(b *testing.B) {
	s1 := "hello"
	s2 := "world"
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		s1 = s1 + " " + s2
	}
}

结果

$ go test -bench=. -benchmem string_test.go 
goos: linux
goarch: amd64
Benchmark1-4   	  114850	    193831 ns/op	  694282 B/op	       5 allocs/op
Benchmark2-4   	  121273	     97109 ns/op	  367785 B/op	       1 allocs/op
PASS
ok  	command-line-arguments	34.278s

s3 = s1 + s2

代码

//string_test.go
package string_test

import (
	"fmt"
	"testing"
)

func Benchmark1(b *testing.B) {
	s1 := "hello"
	s2 := "world"
	s3 := ""
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		s3 = fmt.Sprintf("%s %s", s1, s2)
	}

	_ = s3
}

func Benchmark2(b *testing.B) {
	s1 := "hello"
	s2 := "world"
	s3 := ""
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		s3 = s1 + " " + s2
	}
	_ = s3
}

结果

$ go test -bench=. -benchmem string_test.go 
goos: linux
goarch: amd64
Benchmark1-4   	 6056005	       196 ns/op	      48 B/op	       3 allocs/op
Benchmark2-4   	20536944	        54.9 ns/op	      16 B/op	       1 allocs/op
PASS
ok  	command-line-arguments	2.601s

备注

  • 以上结果均在本地虚拟机上跑出的结果
  • 命令:go test -bench=. -benchmem string_test.go

疑惑

  • s1 = s1 + s2s3 = s1 + s2的对比耗时差距过大的原因?
  • benchmark耗时到底是如何进行计算的?
  • 两个对比测试时,分配内存的次数感觉也挺奇怪?

@maronghe
Copy link

是否可以扩展一下 deadlock 分析过程和有哪些解决方案呢?

@changkun
Copy link
Member Author

是否可以扩展一下 deadlock 分析过程和有哪些解决方案呢?

这是另一个话题了,建议提 issue 发起话题,进入申请流程

@changkun changkun changed the title 第 83 期对 Go 程序进行可靠的性能测试 第 83 期 对 Go 程序进行可靠的性能测试 Mar 26, 2020
@yangwenmai yangwenmai unpinned this issue Mar 26, 2020
@yangwenmai yangwenmai changed the title 第 83 期 对 Go 程序进行可靠的性能测试 第 83 期对 Go 程序进行可靠的性能测试 Mar 26, 2020
@yangwenmai yangwenmai added 已分享 ✅ Go 夜读的分享状态:分享已完成。 and removed 已排期 🗓️ Go 夜读的分享状态:已确定分享时间。 labels Mar 27, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Go 夜读 Go 夜读:主题分享 工程实践与架构设计 Go 夜读分享主题:一些工程实践,架构设计等的经验总结分享 已分享 ✅ Go 夜读的分享状态:分享已完成。
Projects
None yet
Development

No branches or pull requests

5 participants