高质量编程简介及编码规范2 | 青训营笔记

41 阅读2分钟

三.高质量编程简介及编码规范2

2.1.性能优化建议 Benchmark

  • 性能表现需要实际数据衡量
  • Go语言提供了支持基准性能测试的benchmark
 go test -bench=. -benchmem

2.2.性能优化建议 Slice

2.2.1.slice 预分配内存

注意点: 尽可能在使用 make() 初始化切片时提供容量信息

对于切片的理解:

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

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

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

2.2.2.slice 大内存未释放

  • 在已有切片基础上创建切片, 不会创建新的底层数组

  • 场景

    • 原切片较大, 代码在原切片基础上新建小切片
    • 原底层数组在内存中有引用, 得不到释放
  • 可使用 copy 替代 re-slice

 go test -run=. -v

2.3.性能优化建议 Map

  • map 预分配内存

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

2.4.性能优化建议 字符串处理

  • 使用 stirngs.Builder

性能对比:

"+" 拼接 < stirngs.Builder = bytes.Buffer < strings.Buffer

分析:

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

2.5.性能优化建议 空结构体

空结构体节省内存

  • 空结构体 struct{} 实例不占据任何的内存空间

  • 可作为各种场景下的占位符使用

    • 节省资源
    • 空结构体本身具备很强的语义, 即这里不需要任何值, 仅作为占位符

2.6.性能优化建议 atomic包

  • 锁的实现是通过操作系统来实现, 属于系统调用
  • atomic 操作是通过硬件实现, 效率比锁高
  • sync.Mutex 应该用来保护一段逻辑, 不仅仅用于保护一个变量
  • 对于非数值操作, 可以使用 atomic.Value, 能承载一个 interface{}