高质量编程与性能调优课程学习笔记(2) | 青训营笔记

58 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天

高质量编程与性能调优学习总结

性能优化建议

关于Slice

Slice预分配内存

  • 我们在编写代码的过程中,最好尽可能的使用make()初始化切片的时候提供切片的容量信息

  • 切片的本质是一个数组片段的描述

    • 包括数组指针
    • 片段的长度
    • 片段的容量(在不改变内存分配情况下的最大长度)
  • 切片操作并不复制切片指向的元素

  • 当我们创建一个新的切片时会复用原来切片的底层数组

type slice struct {
    array unsafe.Pointer
    len int
    cap int
}
  • slice的另外一个缺陷:存在大内存未释放的情况
  • 在已有切片的基础上创建切片,不会创建新的底层数组,我们可以使用copy来代替re-slice

关于Map

Map预分配内存

  • 不断地向map中添加元素的操作会触发map的扩容
  • 提前分配好空间可以减少内存的拷贝和 Rehash 的消耗
  • 我们可以根据项目的实际需求来提前预估和准备需要的空间

关于字符串处理

在go语言开发学习中,存在如下几个常见的字符串拼接方法

第一种

func Plus(n int, str string) string {
    s := ""
    for i:=0; i<n; i++ {
        s += str
    }
    return s
}

第二种

func StrBuilder(n int, str string) string {
    var builder strings.Builder
    for i:=0; i<n; i++ {
        builder.WriteString(str)
    }
    return builder.String()
}

第三种

func ByteBuffer(n int, str string) string {
    buf := new(bytes.Buffer)
    for i:=0; i<n; i++ {
        buf.WriteString(str)
    }
    return buf.String()
}

性能评估结果:使用 + 拼接性能最差,strings.Builder,bytes.Buffer相近,strings.Builder更快

原因:

  • 字符串在go语言中是不可变类型,占用内存大小是固定的
  • 使用 + 每次都会重新分配内存
  • strings.Builder,bytes.Buffer 底层都是 []byte 数组
  • 内存扩容策略,不需要每次拼接重新分配内存