封闭基准,匿名函数和普通函数

时间:2018-07-20 17:30:42

标签: 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() {
            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

如果我将变量的定义移出循环,则时间相等。

1 个答案:

答案 0 :(得分:1)

除此之外,某些代码生成和某些优化比其他方法更容易实现。有关详细信息,请参见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

bench_test.go

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)
        }
    }
}