用于循环速度比较



我想知道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(。

最新更新