• 【Go开源宝藏】基于 Golang 语法的性能调优技巧(数组的遍历)


    1. 数组的遍历

    数组和切片的遍历方式一样,所以我们这里就不进行区分。

    我们一般用以下两种方式

    • 直接取下标方式
    for i:=0;i<len(nums);i++{
    	...
    }
    
    • 1
    • 2
    • 3

    我们先来讲一下这种方式,我们都知道数组在内存中存储是连续的。所以我们直接用下表取出数组中的元素,就是直接在数组的原地址中获取,这种写法比较像c语言的写法。所以这种方式是非常快的。

    • range 遍历方式
    for index,item := range items{
    	...
    }
    
    • 1
    • 2
    • 3

    我们再来讲一下这种方式,这种方式的情况比第一种要更加美观,和python的 for 循环遍历比较像 ,但是同样的,在遍历items数组的过程中,其实我们得到的item只是一个拷贝的值,也就是会在内存中拷贝一份items中的元素。虽然这种遍历方式比较美观,但是这较于第一种来说是,其性能是有所降低的。

    benchmark测试

    下面的这一段测试逻辑就是将三种遍历的方式进行 benchmark 测试,事先进行赋值并转化成字符串,然后再进行相同的操作,将字符串进行拼接。

    为了测试结果尽可能的快,所以我们的字符串拼接使用了string.builder这个方法来执行。

    /*
    100000
    BenchmarkByRange
    BenchmarkByRange-8         	     763	   1393727 ns/op
    BenchmarkByIndex
    BenchmarkByIndex-8         	    1503	   1194054 ns/op
    BenchmarkByIndexAndLen
    BenchmarkByIndexAndLen-8   	    1818	    745112 ns/op
    */
    
    func BenchmarkByRange(b *testing.B) {
    	elems := make([]string, 100000, 100000)
    	for i := 0; i < 100000; i++ {
    		elems[i] = strconv.Itoa(i)
    	}
    	var builder strings.Builder
    	b.ResetTimer()
    	for i := 0; i < b.N; i++ {
    		for _, elem := range elems {
    			builder.WriteString(elem)
    		}
    	}
    	b.StopTimer()
    }
    
    func BenchmarkByIndex(b *testing.B) {
    	elems := make([]string, 100000, 100000)
    	for i := 0; i < 100000; i++ {
    		elems[i] = strconv.Itoa(i)
    	}
    	var builder strings.Builder
    	b.ResetTimer()
    	for i := 0; i < b.N; i++ {
    		for j := 0; j < len(elems); j++ {
    			builder.WriteString(elems[j])
    		}
    	}
    	b.StopTimer()
    }
    
    func BenchmarkByIndexAndLen(b *testing.B) {
    	elems := make([]string, 100000, 100000)
    	for i := 0; i < 100000; i++ {
    		elems[i] = strconv.Itoa(i)
    	}
    	length := len(elems)
    	var builder strings.Builder
    	b.ResetTimer()
    	for i := 0; i < b.N; i++ {
    		for j := 0; j < length; j++ {
    			builder.WriteString(elems[j])
    		}
    	}
    	b.StopTimer()
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    在上面的测试代码中,我们可以看出,第二种是要比第一种性能稍微高了一点。

    而第三种和第二种的区别就是将数组长度往外放,也就是说,当我们需要在一段逻辑中不断遍历这个数组,我们可以事先规定好长度,因为len(nums)也是有性能影响的,所以我们在遍写代码的时候可以稍微注意一下。

  • 相关阅读:
    Explainability for Large Language Models: A Survey
    2023年数维杯数学建模C题宫内节育器的生产求解全过程文档及程序
    MaTiJi - MT2073 - 上传头像
    Android中内存泄漏的检测,解决方案以及示例
    电力系统直流潮流分析【N-1】(Matlab代码实现)
    鸿蒙开发实例 | 分布式涂鸦
    基于单片机的推箱子游戏仿真设计(#0014)
    ruoyi-vue-pro 项目安装使用过程中的问题解决
    笔试强训Day3
    buu web部分wp
  • 原文地址:https://blog.csdn.net/weixin_45304503/article/details/125839268