【小测试】golang中数组边界检查的开销大约是1.87%~3.12%

作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢!


对比C/C++, golang等类型安全的语言会在数组访问的代码前,通过编译器加入边界检查的代码。
当发生越界的时候,引发panic,而不是实际发生越界导致的结果异常甚至程序崩溃。

因此,本实验通过对比有边界检查和无边界检查的情况,对比边界检查带来的性能开销:

// 有边界检查的情况
func Benchmark_arr_range_check_1(b *testing.B) {
	arr := make([]byte, 1024*1024)
	index := make([]int, 1024*32)
	for i := 0; i < len(index); i++ {
		index[i] = rand.Intn(len(arr))
	}
	b.ResetTimer()
	for n := 0; n < b.N; n++ {
		for i := 0; i < len(index); i++ {
			arr[index[i]]++  //普通的数组访问,每次访问数组的耗时大约是 1.44ns
		}
	}
}

// 无边界检查的情况
func Benchmark_arr_range_check_2(b *testing.B) {
	arr := make([]byte, 1024*1024)
	index := make([]int, 1024*32)
	for i := 0; i < len(index); i++ {
		index[i] = rand.Intn(len(arr))
	}
	b.ResetTimer()
	for n := 0; n < b.N; n++ {
		for i := 0; i < len(index); i++ {
			offset := index[i]
			(*(*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(&arr[0])) + uintptr(offset))))++  // 通过unsafe代码来绕过边界检查,每次数组访问耗时大约 1.41ns
		}
	}
}
  • 总结:
    • 当涉及大量数组访问的场合,比如很大的定长 local cache的情形,可以通过unsafe去掉边界检查
    • 当某个算法使用查表法来获取数据,适合去掉边界检查

posted on 2022-04-29 19:38  ahfuzhang  阅读(79)  评论(0)    收藏  举报