一、性能优化
1.Benchmark
Go 语言提供了支持基准性能测试的 benchmark 工具
go test -bench=.-benchmem
2.Silce(预分配内存)
尽可能使用make()初始化切片提供的容量信息
切片本质是一个数组片段的描述
- 包括数组指针
- 片段的长度
- 片段的容量(不改变内存分配情况下的最大长度)
切片操作并不复制切片指向的元素
创建一个新的切片会复用原来切片的底层数组
>另一个陷阱:大内存未释放
在已有切片基础上创建切片,不会创建新的底层数组
场景
- 原切片较大,代码在原切片基础上新建小切片
- 原底层数组在内存中有引用,得不到释放
可使用copy 替代re-slice
3.map
不断向map 中添加元素的操作会触发 map 的扩容
提前分配好空间可以减少内存拷贝和 Rehash 的消耒
建议根据实际需求提前预估好需要的空间
4.字符串处理
>使用 strings.Builder
使用+ 拼接性能最差,strings.Builder, bytes.Buffer 相近,strings.Buffer 更快
分析:
字符串在 Go 语言中是不可变类型,占用内存大小是固定的
使用+ 每次都会重新分配内存
strings.Builder, bytes.Buffer 底层都是 []byte 数组
内存扩容策略,不需要每次拼接重新分配内存
5.空结构体
>使用空结构体节省内存
空结构体本身具备很强的语义,即这里不需要任何值,仅作为占位符
6.atomic包
>使用 atomic包
锁的实现是通过操作系统来实现,属于系统调用
atomic 操作是通过硬件实现,效率比锁高
sync.Mutex 应该用来保护一段逻辑,不仅仅用于保护一个变量
对于非数值操作,可以使用 atornic.Valuve,能承载一个 interface{}