一、性能优化建议
1. 使用Benchmark工具
go test -bench=. -benchmem
参数含义:
- BenchmarkFib10-8: BenchmarkFib10是测试函数名,-8 表示GOMAXPROCS的值为8
- 1855870: 表示一共执行1855870次即b.N的值
- 602.5 ns/op: 每次执行花费602.5ns
- 0 B/op: 每次执行申请多大的内存
- 0 allocs/op: 每次执行申请几次内存
2.slice预分配内存
- 效果:使用make(【】int, 0,size)初始化切片时提供容量信息,有size会减少执行时间(大约优化到原来的1/3)、申请的内存大小,申请内存次数。
- 切片本质:是一个数组片段的描述,包括数组指针、片段的长度、片段的容量(不改变内存分配情况下的最大长度)
- 切片操作并不复制切片指向的元素,切片和源数组指向的是同一个底层数组。创建一个新的切片会复用原来切片的底层数组。
- 另一个陷阱,大内存未释放:在已有切片基础上创建切片,不会创建新的底层数组。场景:原切片较大,代码在原切片基础上新建小切片;原底层数组在内存中有引用。得不到释放可使用copy 替代 re-slice
3. map预分配内存
- 不断向map中添加元素的操作会触发map 的扩容
- 提前分配好空间可以减少内存拷贝和Rehash的消耗
- 建议根据实际需求提前预估好需要的空间
4.字符串处理
性能比较:“+”拼接(最差) < strings.Builder ≈ bytes.Buffer < strings.Buffer(最好)
5.空结构体
空结构体struct{}不占据内存,可以作为占位符使用
6.使用atomic包
- 锁的实现是通过操作系统来实现,属于系统调用
- atomic 操作是通过硬件实现,效率比锁高
- sync.Mutex 应该用来保护一段逻辑,不仅仅用于保护一个变量
- 对于非数值操作,可以使用 atomic.Value,能承载一个 interface{}