我想知道len
操作员在GO中的速度有多快,我写了一个简单的基准测试标准。我的期望是,通过避免在每次循环迭代期间调用len
,代码运行速度会更快,但实际上是相反的。
这是基准:
func sumArrayNumber(input []int) int {
var res int
for i, length := 0, len(input); i < length; i += 1 {
res += input[i]
}
return res
}
func sumArrayNumber2(input []int) int {
var res int
for i := 0; i < len(input); i += 1 {
res += input[i]
}
return res
}
var result int
var input = []int{3, 6, 22, 68, 11, -7, 22, 5, 0, 0, 1}
func BenchmarkSumArrayNumber(b *testing.B) {
var r int
for n := 0; n < b.N; n++ {
r = sumArrayNumber(input)
}
result = r
}
func BenchmarkSumArrayNumber2(b *testing.B) {
var r int
for n := 0; n < b.N; n++ {
r = sumArrayNumber2(input)
}
result = r
}
这是结果:
goos: windows
goarch: amd64
BenchmarkSumArrayNumber-8 300000000 4.75 ns/op
BenchmarkSumArrayNumber2-8 300000000 4.67 ns/op
PASS
ok command-line-arguments 4.000s
我通过执行以下操作确认电阻是一致的:
- 将输入阵列大小加倍,大约是每个OP执行时间的两倍。速度差为输入阵列的长度。
- 交换测试顺序不会影响结果。
为什么在每个循环迭代中检查Len((的代码更快?
一个人可能会争辩说,0.08ns的差异在统计学上与说一个循环速度比另一个较快的速度无关。您可能需要多次运行相同的测试(至少超过20次(,此时您应该能够得出平均值和标准变化。
此外,有许多因素可以加速len()
操作员。例如CPU缓存和编译器优化。我认为您特定示例中最相关的因素是Slice和Array的len()
操作员只是在Slice的数据结构中读取len
字段。因此,是o(1(。