在开发过程中,我们总是在设计不同的数据结构和不同的算法对数据进行组织和存取,有些场合我们可以用硬编码或者代码生成器来生成一组函数按条件返回数据,另外一些场合我们可以把数据存储在slice当中,需要查找时就遍历查找,又或者有的场合我们可以用map存储数据,用key来索引数据。这几种数据存取方式在不同数据量的情况下,性能消耗是怎么样的呢?下面做个对比实验。
我们知道go的map数据量不管大小都能保证固定的读取时间,而slice和硬编码肯定无法应对大数据量,所以这里不做大数据量的实验,只做小数据量的实验。
实验代码(github):
package labs06
import "testing"
type BigStruct struct {
C01 int
C02 int
C03 int
C04 int
C05 int
C06 int
C07 int
C08 int
C09 int
C10 int
C11 int
C12 int
C13 int
C14 int
C15 int
C16 int
C17 int
C18 int
C19 int
C20 int
C21 int
C22 int
C23 int
C24 int
C25 int
C26 int
C27 int
C28 int
C29 int
C30 int
}
func Loop1(a []BigStruct) int {
for i := 0; i < len(a); i++ {
if a[i].C30 == 3 {
return i
}
}
return -1
}
func Loop2(a []BigStruct) int {
for i := len(a) - 1; i >= 0; i-- {
if a[i].C30 == 1 {
return i
}
}
return -1
}
func Loop3(a map[int]BigStruct) int {
return a[2].C30
}
func Loop4(a []*BigStruct) int {
for i, x := range a {
if x.C30 == 3 {
return i
}
}
return -1
}
func Loop5(a []BigStruct) int {
switch {
case a[0].C01 == 3:
return 0
case a[1].C01 == 3:
return 1
case a[2].C01 == 3:
return 2
}
return -1
}
func Benchmark_Loop1(b *testing.B) {
var a = make([]BigStruct, 3)
a[0].C30 = 1
a[1].C30 = 2
a[2].C30 = 3
for i := 0; i < b.N; i++ {
Loop1(a)
}
}
func Benchmark_Loop2(b *testing.B) {
var a = make([]BigStruct, 3)
a[0].C30 = 1
a[1].C30 = 2
a[2].C30 = 3
for i := 0; i < b.N; i++ {
Loop2(a)
}
}
func Benchmark_Loop3(b *testing.B) {
var a = make(map[int]BigStruct, 3)
a[0] = BigStruct{C30: 1}
a[1] = BigStruct{C30: 2}
a[2] = BigStruct{C30: 3}
for i := 0; i < b.N; i++ {
Loop3(a)
}
}
func Benchmark_Loop4(b *testing.B) {
var a = make([]*BigStruct, 3)
a[0] = &BigStruct{C30: 1}
a[1] = &BigStruct{C30: 2}
a[2] = &BigStruct{C30: 3}
for i := 0; i < b.N; i++ {
Loop4(a)
}
}
func Benchmark_Loop5(b *testing.B) {
var a = make([]BigStruct, 3)
a[0].C30 = 1
a[1].C30 = 2
a[2].C30 = 3
for i := 0; i < b.N; i++ {
Loop5(a)
}
}
试验结果:
dada-imac:labs dada$ go test -test.bench="." labs06 testing: warning: no tests to run PASS Benchmark_Loop1 500000000 5.73 ns/op Benchmark_Loop2 500000000 5.72 ns/op Benchmark_Loop3 50000000 68.0 ns/op Benchmark_Loop4 500000000 4.92 ns/op Benchmark_Loop5 500000000 4.40 ns/op ok labs06 15.970s
结论:硬编码 < 指针slice的range循环 < for循环,但是量级是一样的,看情况用。但是map差了一个量级,小数据量尽量少用。
有疑问加站长微信联系(非本文作者)
![](https://static.golangjob.cn/static/img/footer.png?imageView2/2/w/280)