Go 闭包、匿名函数和普通函数的基准
我测试了一些函数,不明白为什么闭包和匿名函数的执行时间不同:Go 闭包、匿名函数和普通函数的基准,go,Go,我测试了一些函数,不明白为什么闭包和匿名函数的执行时间不同: package main import ( "fmt" "time" ) func X(p *int) { *p += 1 } func main() { n := 1000000000 t0 := time.Now() for i := 0; i < n; i++ { p := 0 x := func(
package main
import (
"fmt"
"time"
)
func X(p *int) {
*p += 1
}
func main() {
n := 1000000000
t0 := time.Now()
for i := 0; i < n; i++ {
p := 0
x := func() {
p += 1
}
x()
}
fmt.Printf("Closure: %v\n", time.Since(t0))
t0 = time.Now()
for i := 0; i < n; i++ {
p := 0
func() {
p += 1
}()
}
fmt.Printf("Anonymous function: %v\n", time.Since(t0))
t0 = time.Now()
for i := 0; i < n; i++ {
p := 0
X(&p)
}
fmt.Printf("Function: %v\n", time.Since(t0))
return
}
结果:
558.84667ms
267.847834ms
271.102576ms
如果我将变量的定义移出循环,时间是相等的。除此之外,一些代码生成和一些优化比其他更容易完成。有关详细信息,请参阅Go gc编译器源代码
$ go version
go version devel +e68ac45172 Fri Jul 20 16:04:01 2018 +0000 linux/amd64
未优化:
$ go test bench_test.go -bench=. -benchmem -gcflags='-N'
goos: linux
goarch: amd64
BenchmarkClosure-4 1 2621664326 ns/op 0 B/op 0 allocs/op
BenchmarkAnonymous-4 1 1995507678 ns/op 0 B/op 0 allocs/op
BenchmarkFunction-4 1 2297303813 ns/op 0 B/op 0 allocs/op
优化:
$ go test bench_test.go -bench=. -benchmem
goos: linux
goarch: amd64
BenchmarkClosure-4 2 585091582 ns/op 0 B/op 0 allocs/op
BenchmarkAnonymous-4 5 287299925 ns/op 0 B/op 0 allocs/op
BenchmarkFunction-4 5 287710165 ns/op 0 B/op 0 allocs/op
台架试验(go):
第一个和第二个示例都是闭包,它们关闭外部作用域中的变量,并且都是匿名函数,函数未命名。此外,还可以尝试使用Go附带的基准测试工具进行基准测试,而不是使用自己的工具,附带的工具制作得非常好。最后一点这种微基准测试很可能会产生不准确的性能数据。如果你将时间除以100000000,每次调用的时间为.27到.56纳秒-你的基准测试基本上什么都不做,你测量的是一些无意义的开销指令。您还应该使用内置的基准测试工具,而不是试图手动计时。十亿个变量分配需要一些时间,这并不奇怪。这也是在优化类中,除非您认真考虑将汇编作为实现路径,否则保存的一两个时钟周期根本不重要,“你最好把你的性能测量和调整工作集中在其他地方。”Adrian bench说results@JimB我对更大的n做了同样的测试。同样的结果。这张长凳也一样。
package main
import "testing"
func X(p *int) {
*p += 1
}
var N = 1000000000
func BenchmarkClosure(b *testing.B) {
for n := 0; n < b.N; n++ {
for i := 0; i < N; i++ {
p := 0
x := func() {
p += 1
}
x()
}
}
}
func BenchmarkAnonymous(b *testing.B) {
for n := 0; n < b.N; n++ {
for i := 0; i < N; i++ {
p := 0
func() {
p += 1
}()
}
}
}
func BenchmarkFunction(b *testing.B) {
for n := 0; n < b.N; n++ {
for i := 0; i < N; i++ {
p := 0
X(&p)
}
}
}