代码之家  ›  专栏  ›  技术社区  ›  hedgehogues

闭包、匿名函数和普通函数的基准

go
  •  -1
  • hedgehogues  · 技术社区  · 6 年前

    我测试了一些函数,我不明白为什么闭包和匿名函数的执行时间不同:

    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.84667毫秒

    267.847834毫秒

    271.102576毫秒

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

    1 回复  |  直到 6 年前
        1
  •  1
  •   peterSO    6 年前

    除此之外,一些代码生成和一些优化比其他更容易完成。有关详细信息,请参阅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)
            }
        }
    }