go语言遍历切片的时候有range,和for下标两种遍历方法,那么哪种性能好呢?直觉上,range是对元素的拷贝,性能必然不如for+下标访问效率高。且看下面的测试。
测试环境
goos: linux
goarch: amd64
go version go1.14 linux/amd64
Run on (8 X 2394.37 MHz CPU s)
CPU Caches:
L1 Data 32 KiB (x8)
L1 Instruction 32 KiB (x8)
L2 Unified 4096 KiB (x8)
L3 Unified 16384 KiB (x1)
测试代码
BufSize模拟切片中每个元素的大小。
ArrSize表示数组大小。 这里取1000,因为循环本身也会有消耗。
//src/benchmark/range_test.go
package main
import (
"testing"
)
const (
BufSize=256
ArrSize=1000
)
type Buff struct {
data [BufSize]uint8
}
func BenchmarkRange(b *testing.B) {
var SomeData = make([]Buff, ArrSize)
for i := 0; i < b.N; i ++ {
for _, d := range SomeData {
_ = len(d.data)
}
}
}
func BenchmarkFor(b *testing.B) {
var SomeData = make([]Buff, ArrSize)
for i := 0; i < b.N; i ++ {
for j:=0; j < len(SomeData); j++ {
_ = len(SomeData[j].data)
}
}
}
go test -v -bench="(Range)|(For)"
测试结果
StructSize | Range ns/op | For ns/op |
0 | 399 | 346 |
1 | 389 | 350 |
2 | 379 | 390 |
4 | 385 | 384 |
8 | 343 | 346 |
16 | 342 | 342 |
32 | 343 | 342 |
64 | 343 | 342 |
72 | 362 | 400 |
76 | 374 | 384 |
80 | 3375 | 342 |
96 | 4173 | 341 |
128 | 5035 | 343 |
256 | 9415 | 345 |
ArrSize: | 1000 |
测试结论
当数组元素大小小于76字节时,两者性能一样。大于76字节时,for range性能明显下降。