Go 中数组和切片的性能对比

433 阅读2分钟

我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第1篇文章,点击查看活动详情

数组和切片

在 Go 中集合有固定大小的数据集,如数组;也有动态大小的数据集,如 Slice 切片。

  • 数组:由固定长度和对固定对象类型所组成的数据类型
var ary [2]int // 定义长度为2的数组
  • 切片:数组的抽象,长度可变化。可以说是动态数组
var sli []int. // 定义了一个未指定大小的切片
var slice1 []type = make([]type, len)// 切片的初始长度
//也可以简写为
slice1 := make([]type, len)

这两个的性能比较是如何的呢?Go 语言标准库内置了支持 benchmark 的 testing 库。所以通过2个基准测试分别对切片和数组进行测试,然后通过分析最终结果验证他们的性能只比。

基准测试 benchmark

  • 和普通单元测试用例医院,都是在 _test.go
  • 函数名必须以Benchmark开头,参数是 b *test.B
  • 执行命令是 go test -bench。 -benchtime 和 -count 两个参数分别指的是执行时间和测试次数

数组基准测试

const MaxSize = 10000

func AddXAry(icount int, b *testing.B) {
    var testAry [MaxSize]int
    for i := 0; i < icount; i++ {
        testAry[i] = i
    }
}

func BenchmarkAddXAry(b *testing.B) {
    b.Run(fmt.Sprintf("item_size_%d", MaxSize), func(b *testing.B) {
        for i := 0; i < b.N; i++ {
            AddXAry(MaxSize, b)
        }
    })
}

执行基准测试命令,结果如下图所示:

2022-09-04-12-18-52-image.png

Slice 切片基准测试

const MaxSize = 10000

func AddXSlice(icount int, b *testing.B) {
    testSlice := []int{}
    for i := 0; i < icount; i++ {
        testSlice = append(testSlice, i)
    }
}

func BenchmarkAddXSlice(b *testing.B) {
    b.Run(fmt.Sprintf("item_size_%d", MaxSize), func(b *testing.B) {
        for i := 0; i < b.N; i++ {
            AddXSlice(MaxSize, b)
        }
    })
}

执行基准测试命令,结果如下图所示:

2022-09-04-12-18-03-image.png

以上两个基准测试例子可以看到通过向数组/切片加数据进行测试他们的性能。通过执行结果就可以很明显得到结论:数组的方法比切片的方法更快。

  • slice_size_10000-10 ,其中-10 就是 GOMAXPROCS ,CPU 核数,可以通过 -cpu 参数修改核数

  • 35919 表示用例执行了 35919 次,总耗时 1.696s

当然,以上只是简单的基准测试,你可以通过设置 CPU 数,增加测试次数,多进行几组测试,可以精准的验证结果。