目录
3. 性能优化建议
3. 性能优化建议
Benchmark: 性能表现需要实际数据衡量。Go 语言提供了支持基准性能测试的 benchmark 工具。
Slice: slice 预分配内存, 尽可能在使用 make() 初始化切片时提供容量信息。切片本质是一个数组片段的描述,包括数组指针,片段的长度,片段的容量(不改变内存分配情况下的最大长度)。切片操作并不复制切片指向的元素。创建一个新的切片会复用原来切片的底层数组。大内存未释放,在已有切片基础上创建切片,不会创建新的底层数组。 场景: 原切片较大,代码在原切片基础上新建小切片,原底层数组在内存中有引用,得不到释放。可用copy替代re-slice.
Map: map 预分配内存,分析:不断向 map 中添加元素的操作会触发 map 的扩容,提前分配好空问可以减少内存拷贝和 Rehash 的消耗,建议根据实际需求提前预估好需要的空间。
字符串处理:使用 strings.Builder, 使用+拼接性能最差, strings.Builder, bytes.Buffer 相近, strings.Buffer 更快。分析:宇符串在 Go 语言中是不可变类型,占用内存大小是固定的。使用+每次都会重新分配内存。strings.Builder, bytes.Buffer 底层都是 []byte 数组。内存扩容策路,不需要每次拼接重新分配内存。bytes.Buffer 转化为宇符串时重 新申请了一块空间。strings.Builder 直接将底层的 []byte 转换成了字符串类型返回。
空结构体:使用空结构体节省内存,空结构体 structD 实例不占据任何的内存空间 可作为各种场景下的占位符使用,节省资源,空结构体本身具备很强的语义,即这里不需要 任何值,仅作为占位符。实现 Set, 可以考虑用 map 来代替。对于这个场景,只需要用到 map 的键,而不需要值。即使是将 map 的值设置为 bool 类型,也会多占据1个字节空间。一个开源实现:github.com/deckarep/go….
atomic 包:使用 atomic 包,锁的实现是通过操作系统来实现,属于系统调用。atomic 操作是通过硬件实现,效率比锁高。sync.Mutex 应该用来保护一段逻辑,不仅仅用于保护一个变量。对于非数值操作,可以使用atomic.Value, 能承载一个interface[].