类型断言将涉及调用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中有一些限制吗?
答案 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
的结果:
testE2I: 30.405681s, testE2T: 1.734307s
具体类型更快,但接口到接口断言要慢得多。