我发现了这个奇怪的基准测试结果,这似乎表明如果不循环执行,分配数组元素的速度会更快。希望有人可以解释它。完整的Go代码在下面,基准BenchmarkDirectAssignment
的运行速度似乎快十倍,即使它在做同样的事情:
package main
import "testing"
func BenchmarkLoopAssignment(b *testing.B) {
arr := make([]int, 10)
for n := 0; n < b.N; n++ {
for i := 0; i < 10; i++ {
arr[i] = n
}
}
}
func BenchmarkDirectAssignment(b *testing.B) {
arr := make([]int, 10)
for n := 0; n < b.N; n++ {
arr[0] = n
arr[1] = n
arr[2] = n
arr[3] = n
arr[4] = n
arr[5] = n
arr[6] = n
arr[7] = n
arr[8] = n
arr[9] = n
}
}
$ go test -bench=.
goos: windows
goarch: amd64
BenchmarkLoopAssignment-16 500000000 3.76 ns/op
BenchmarkDirectAssignment-16 2000000000 0.25 ns/op
PASS
ok _/D_/go_benchmark 3.107s
我已经用Java和C#复制了此代码,并得到了相同的结果-直接分配总是更快。有谁知道为什么会这样?谢谢!
答案 0 :(得分:5)
在第一个示例中,您有一个循环。每次触发至少要跳转1次+修改并检查运行变量。那是您分配作业的开销。
在第二个示例中,您对分配进行了硬编码。这些命令可以按顺序读取。无需跳转,计数或检查相关的间接费用。
但是值得指出的是,这种差异几乎不会发生:
https://ericlippert.com/2012/12/17/performance-rant/
无论如何您都不可以将案例2用于大型列表。至少不是某些自动代码创建的这一方面,
答案 1 :(得分:0)
第一个示例涉及很少的使用cpu内存的额外计算,然后才进行实际分配。 但是对于第二个示例,它是直接分配而无需更多计算。 正如其他答案所提到的,对于本示例案例而言,这并不重要,但是对于更复杂/更大的数据集,算法如何有效工作非常重要。
由于计算是相同的,因此上述结果对于其他编程语言也可能相同。
关于复杂性和big-O的一些好的说明,这可能会有所帮助 http://pages.cs.wisc.edu/~vernon/cs367/notes/3.COMPLEXITY.html