4
4
5
5
func BenchmarkXxx(*testing.B)
6
6
7
- 被认为是基准测试,通过 " go test" 命令,加上 ` -bench ` flag 来执行 。多个基准测试按照顺序运行。
7
+ 被认为是基准测试,通过 ` go test ` 命令,加上 ` -bench ` 标志来执行 。多个基准测试按照顺序运行。
8
8
9
- 基准测试函数样例看起来如下所示 :
9
+ 基准测试函数的形式如下 :
10
10
11
11
``` go
12
12
func BenchmarkHello (b *testing .B ) {
@@ -16,13 +16,13 @@ func BenchmarkHello(b *testing.B) {
16
16
}
17
17
```
18
18
19
- 基准函数会运行目标代码 b.N 次。在基准执行期间,会调整 b.N 直到基准测试函数持续足够长的时间。输出
19
+ 基准函数会运行目标代码 b.N 次。在基准执行期间,程序会自动调整 b.N 直到基准测试函数持续足够长的时间。输出结果形如:
20
20
21
21
BenchmarkHello 10000000 282 ns/op
22
22
23
23
意味着循环执行了 10000000 次,每次循环花费 282 纳秒 (ns)。
24
24
25
- 如果在运行前基准测试需要一些耗时的配置 ,则可以先重置定时器:
25
+ 如果基准测试在循环前需要一些耗时的配置 ,则可以先重置定时器:
26
26
27
27
``` go
28
28
func BenchmarkBigLen (b *testing .B ) {
@@ -33,20 +33,20 @@ func BenchmarkBigLen(b *testing.B) {
33
33
}
34
34
}
35
35
```
36
- 如果基准测试需要在并行设置中测试性能,则可以使用 RunParallel 辅助函数 ; 这样的基准测试一般与 ` go test -cpu ` 标志一起使用:
36
+ 如果基准测试需要在并行设置中测试性能,则可以使用 ` RunParallel ` 辅助函数 ; 这样的基准测试一般与 ` go test -cpu ` 标志一起使用:
37
37
38
38
``` go
39
39
func BenchmarkTemplateParallel (b *testing .B ) {
40
- templ := template.Must (template.New (" test" ).Parse (" Hello, {{.}}!" ))
41
- b.RunParallel (func (pb *testing.PB ) {
42
- // 每个 goroutine 有属于自己的 bytes.Buffer.
43
- var buf bytes.Buffer
44
- for pb.Next () {
45
- // 所有 goroutine 一起,循环一共执行 b.N 次
46
- buf.Reset ()
47
- templ.Execute (&buf, " World" )
48
- }
49
- })
40
+ templ := template.Must (template.New (" test" ).Parse (" Hello, {{.}}!" ))
41
+ b.RunParallel (func (pb *testing.PB ) {
42
+ // 每个 goroutine 有属于自己的 bytes.Buffer.
43
+ var buf bytes.Buffer
44
+ for pb.Next () {
45
+ // 循环体在所有 goroutine 中总共执行 b.N 次
46
+ buf.Reset ()
47
+ templ.Execute (&buf, " World" )
48
+ }
49
+ })
50
50
}
51
51
```
52
52
@@ -100,7 +100,7 @@ ok chapter09/testing 15.361s
100
100
```
101
101
默认情况下,每个基准测试最少运行 1 秒。如果基准测试函数返回时,还不到 1 秒钟,` b.N ` 的值会按照序列 1,2,5,10,20,50,... 增加,同时再次运行基准测测试函数。
102
102
103
- 我们注意到 ` BenchmarkFib40 ` 一共才运行 2 次。为了更精确的结果,我们可以通过增加标志 ` -benchtime ` 来它运行更多次 。
103
+ 我们注意到 ` BenchmarkFib40 ` 一共才运行 2 次。为了更精确的结果,我们可以通过 ` -benchtime ` 标志指定运行时间,从而使它运行更多次 。
104
104
105
105
```
106
106
$ go test -bench=Fib40 -benchtime=20s
@@ -111,7 +111,7 @@ BenchmarkFib40-4 30 838675800 ns/op
111
111
112
112
B 是传递给基准测试函数的一种类型,它用于管理基准测试的计时行为,并指示应该迭代地运行测试多少次。
113
113
114
- 一个基准测试在它的基准测试函数返回时,又或者在它的基准测试函数调用 ` FailNow ` 、` Fatal ` 、` Fatalf ` 、` SkipNow ` 、` Skip ` 或者 ` Skipf ` 中的任意一个方法时,测试即宣告结束 。至于其他报告方法,比如 ` Log ` 和 ` Error ` 的变种,则可以在其他 goroutine 中同时进行调用。
114
+ 当基准测试函数返回时,或者当基准测试函数调用 ` FailNow ` 、` Fatal ` 、` Fatalf ` 、` SkipNow ` 、` Skip ` 、 ` Skipf ` 中的任意一个方法时,则宣告测试函数结束 。至于其他报告方法,比如 ` Log ` 和 ` Error ` 的变种,则可以在其他 goroutine 中同时进行调用。
115
115
116
116
跟单元测试一样,基准测试会在执行的过程中积累日志,并在测试完毕时将日志转储到标准错误。但跟单元测试不一样的是,为了避免基准测试的结果受到日志打印操作的影响,基准测试总是会把日志打印出来。
117
117
@@ -122,14 +122,14 @@ B 类型中的报告方法使用方式和 T 类型是一样的,一般来说,
122
122
有三个方法用于计时:
123
123
124
124
1 . StartTimer:开始对测试进行计时。该方法会在基准测试开始时自动被调用,我们也可以在调用 StopTimer 之后恢复计时;
125
- 2 . StopTimer:停止对测试进行计时。当你需要执行一些复杂的初始化操作,并且你不想对这些操作进行测量时,就可以使用这个方法来暂时地停止计时。
125
+ 2 . StopTimer:停止对测试进行计时。当你需要执行一些复杂的初始化操作,并且你不想对这些操作进行测量时,就可以使用这个方法来暂时地停止计时;
126
126
3 . ResetTimer:对已经逝去的基准测试时间以及内存分配计数器进行清零。对于正在运行中的计时器,这个方法不会产生任何效果。本节开头有使用示例。
127
127
128
128
### 并行执行 ###
129
129
130
- 通过 ` RunParallel ` 方法以并行的方式执行给定的基准测试。 RunParallel 会创建出多个 goroutine,并将 b.N 分配给这些 goroutine 执行,其中 goroutine 数量的默认值为 GOMAXPROCS。用户如果想要增加非 CPU 受限(non-CPU-bound)基准测试的并行性,那么可以在 RunParallel 之前调用 SetParallelism(如 SetParallelism(2),则 goroutine 数量为 2* GOMAXPROCS)。RunParallel 通常会与 -cpu 标志一同使用。
130
+ 通过 ` RunParallel ` 方法能够并行地执行给定的基准测试。 ` RunParallel ` 会创建出多个 goroutine,并将 b.N 分配给这些 goroutine 执行,其中 goroutine 数量的默认值为 GOMAXPROCS。用户如果想要增加非 CPU 受限(non-CPU-bound)基准测试的并行性,那么可以在 ` RunParallel ` 之前调用 ` SetParallelism ` (如 ` SetParallelism(2) ` ,则 goroutine 数量为 2* GOMAXPROCS)。` RunParallel ` 通常会与 ` -cpu ` 标志一同使用。
131
131
132
- ` body ` 函数将在每个 goroutine 中执行,这个函数需要设置所有 goroutine 本地的状态,并迭代直到 ` pb.Next ` 返回 false 值为止。因为 ` StartTimer ` 、` StopTime ` 和 ` ResetTimer ` 这三个方法都带有全局作用,所以 body 函数不应该调用这些方法; 除此之外,body 函数也不应该调用 Run 方法。
132
+ ` body ` 函数将在每个 goroutine 中执行,这个函数需要设置所有 goroutine 本地的状态,并迭代直到 ` pb.Next ` 返回 false 值为止。因为 ` StartTimer ` 、` StopTime ` 和 ` ResetTimer ` 这三个方法都带有全局作用,所以 ` body ` 函数不应该调用这些方法; 除此之外,` body ` 函数也不应该调用 ` Run ` 方法。
133
133
134
134
具体的使用示例,在本节开头已经提供!
135
135
@@ -161,26 +161,26 @@ func BenchmarkTmplExucte(b *testing.B) {
161
161
162
162
### 基准测试结果 ##
163
163
164
- 对
165
-
166
- BenchmarkTmplExucte-4 2000000 898 ns/op 368 B/op 9 allocs/op
167
-
168
- 中的每一项,你是否都清楚是什么意思呢?
164
+ 对上述结果中的每一项,你是否都清楚是什么意思呢?
169
165
170
- ` testing ` 包中的 ` BenchmarkResult ` 类型能为你提供帮助。它保存了基准测试的结果。
166
+ - ` 2000000 ` :基准测试的迭代总次数 b.N
167
+ - ` 898 ns/op ` :平均每次迭代所消耗的纳秒数
168
+ - ` 368 B/op ` :平均每次迭代内存所分配的字节数
169
+ - ` 9 allocs/op ` :平均每次迭代的内存分配次数
171
170
172
- 它的定义如下 :
171
+ ` testing ` 包中的 ` BenchmarkResult ` 类型能为你提供帮助,它保存了基准测试的结果,定义如下 :
173
172
174
173
``` go
175
174
type BenchmarkResult struct {
176
- N int // The number of iterations. 即 b.N
177
- T time.Duration // The total time taken. 基准测试花费的时间
175
+ N int // The number of iterations. 基准测试的迭代总次数, 即 b.N
176
+ T time.Duration // The total time taken. 基准测试的总耗时
178
177
Bytes int64 // Bytes processed in one iteration. 一次迭代处理的字节数,通过 b.SetBytes 设置
179
- MemAllocs uint64 // The total number of memory allocations. 总的分配内存的次数
180
- MemBytes uint64 // The total number of bytes allocated. 总的分配内存的字节数
178
+ MemAllocs uint64 // The total number of memory allocations. 内存分配的总次数
179
+ MemBytes uint64 // The total number of bytes allocated. 内存分配的总字节数
181
180
}
182
181
```
183
- 该类型还提供了相应的计算每个操作每秒相应指标的方法。示例如下:
182
+
183
+ 该类型还提供了每次迭代操作所消耗资源的计算方法,示例如下:
184
184
185
185
``` go
186
186
package main
0 commit comments