golang:如何解释类​​型断言效率?

时间:2015-07-23 03:10:28

标签: go

类型断言将涉及调用runtime.assertE2T或runtime.assertE2I(您可以看到汇编代码)。

package main

import (
    "fmt"
    "time"
)

type I interface {
    echo()
}

type A struct{}

func (a *A) echo() {}

type testfn func()

func run(f testfn) {
    ts := time.Now()
    f()
    te := time.Now()
    fmt.Println(te.Sub(ts))
}

func testE2T() {
    var i interface{} = new(A)
    for a := 0; a < 500000000; a++ {
        _ = i.(*A)
    }
}

func testE2I() {
    var i interface{} = new(A)
    for a := 0; a < 500000000; a++ {
        _ = i.(I)
    }
}

func main() {
    fmt.Println("testE2I:")
    run(testE2I)
    fmt.Println("testE2T:")
    run(testE2T)
}

结果:

testE2I:
11.065225934s
testE2T:
5.720773381s

似乎类型断言比C中的指针慢?怎么解释呢?

奇怪的是,当我使用gccgo运行相同的程序时,会导致内存不足错误。 gccgo在gc中有一些限制吗?

1 个答案:

答案 0 :(得分:4)

我无法弄清楚你的问题是什么,但我会尽力回答你问的问题。

  

似乎类型断言比C中的指针慢?

是的,确实如此。类型断言在运行时需要是安全的,因此需要执行许多checks。接口到接口断言的情况更糟,因为您还需要确保该类型实现接口。

据说,他们肯定能表现得更好。实际上,这里是对Go 1.4.2的基准测试结果的比较。 vs Go 1.5的最新开发版:

  • 转到1.4.2:testE2I: 10.014922955s, testE2T: 4.465621814s

  • Go 1.5 dev:testE2I: 7.201485053s, testE2T: 287.08346ms

现在它的速度提高了十倍以上,Go 1.6的新SSA后端可能会带来更好的优化。

  

奇怪的是,当我使用gccgo运行相同的程序时,会导致内存不足错误。 gccgo在gc中有一些限制吗?

我的猜测是gccgo缺乏逃避分析,但我可能错了。我实际上能够在我的机器上使用gccgo运行基准测试,但它消耗了大约9 GB的RAM,这是正常的一切。我很确定filing an issue关于那不会受到伤害。无论如何,这是-O3的结果:

  • gccgo:testE2I: 30.405681s, testE2T: 1.734307s

具体类型更快,但接口到接口断言要慢得多。