GO语言高质量编程--性能优化建议 | 青训营笔记

147 阅读2分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第4篇笔记, 第三次课主要讲了GO语言的高质量变成和性能调优实战,本文是针对性能优化建议部分做的笔记。

一、Benchmark

  • 性能表现需要实际数据衡量
  • Go语言提供了支持基准性能测试的benchmark工具

  • 使用命令
$ go test -bench=. -benchmem
  • 结果

二、Slice优化建议

1. 预分配内存

  • 尽可能在使用make初始化切片的时候提供容量信息
  • 切片本质是数组片段的描述

slice底层结构

type slice struct{
    array unsafe.Pointer
    len int
    cap int
}

2. 大内存未释放

  • 在已有切片的基础上创建切片,不会创建新的底层数组
  • 可以使用copy代替re-slice

\

\

三、map优化建议

1.map预分配内存

这个和slice原理类似

  • 不断向map中添加元素会导致map扩容
  • 提前分配好空间会减少内存拷贝和rehash的消耗

四、字符串性能优化

1. 使用strings.Builder

  • 常见的字符串拼接方式

  • 性能分析
    • 使用+拼接性能最差, strings.Builder, bytes.Buffer相近,strings.Builder更快
    • 每次+都会重新分配内存
    • strings.Builder底层是[]byte数组
    • 使用的是内存扩容策略,不需要每次重新分配内存

五、使用空结构体性能优化

  • 使用空结构体struct{}实例,不占任何内存空间
  • 可以做各种场景下的占位符使用
    • 节省资源
    • 作为占位符

\

用途

  • 实现Set,可以考虑用map的key实现,value设置为空结构体
  • 即使将map的value设置为bool类型,也会多占据一个字节空间

六、使用atomic包优化

在针对单个变量的并发操作场景下,可以使用atomic包代替并发锁

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