本文已参与「新人创作礼」活动,一起开启掘金创作之路。
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性能明显下降。