青训营笔记 - Go的简单性能优化

63 阅读2分钟

性能优化是编写高质量,高可用性代码不可或缺的一部分,本章跟随课程学习Go的性能优化相关内容。

什么是性能优化

前提:满足正确可靠、简洁清晰等质量因素 效率评估:性能优化是时空效率综合评估,有时候时间效率和空间效率会相互对立 测试工具:以下默认为Go提供的benchmark工具,进行实际数据衡量

性能优化的原则

  • 依靠数据而不是猜测
  • 定位最大瓶颈而不是细枝末节
  • 不要过早优化
  • 不要过度优化

Slice

slice作为基本操作之一,用途十分广泛,它的优化也因此至关重要。

预分配内存

尽可能使用make在初始化切片时提供容量信息

func NoPreAlloc(sizze int){
    data := make([]int, 0)
    for k := 0; k < size; k++ {
        data = append(data, k)
    }
}

上为未提供初始容量信息,下为提供

func NoPreAlloc(sizze int){
    data := make([]int, 0, size)
    for k := 0; k < size; k++ {
        data = append(data, k)
    }
}

图片.png

图片.png

大内存未释放问题

大内存如果没能得到及时释放会严重影响运行空间。由于Go和python一样都是自动垃圾回收机制,所以需要注意该陷阱。比如沼泽里有origin大内存切片,希望在已有基础上创建新的切片,可以用copy代替re-slice。

func GetLastBySlice(origin []int) []int{
    return origin[len(origin)-2:]
}

func GetLastByCopy(origin []int) []int{
    result := make([]int, 2)
    copy(result, origin[len(origin)-2:])
    return result
}

如下图所示,copy明显更优

图片.png

map

类似于slice操作,基本思想都是不断添加元素需要先扩容再添加,频繁的内存拷贝,rehash等操作会带来极大消耗,所以建议根据实际需求提前预估好需要的空间。

strings

多用内置函数,和python类似,不要直接用“+”拼接字符串,这样需要重新分配内存,内置函数考虑到底层的[]byte操作,转为字符串类型返回

性能分析工具pprof

希望知道什么地方耗费了多少CPU,memory, pprof用于可是怀和分析性能分析数据的工具