性能优化 | 青训营笔记

67 阅读2分钟

这是我参与「第五届青训营」伴学笔记创作活动的第 11 天

本节重点

了解什么是性能优化,性能优化可以从哪些点出发进行,如何进行实际操作。

简介

性能优化的前提是满足正确可靠、简洁清晰等质量因素。

性能优化是综合评估,有时候时间效率和空间效率可能对立。

针对 Go 语言特性,介绍 Go 相关的性能优化建议。

性能优化 - Benchmark

go test -bench=. -benchmem

结果说明:

image.png

BenchmarkFib10是测试函数名-8 表示GOMAXPROCS的值为8,表示一共执行1855870次即b.N的值,每次执行花费602.5ns,每次执行申请多大的内存,每次执行申请几次内存。

Slice

slice 预分配内存: 尽可能在使用 make() 初始化切片时提供容量信息。

性能对比: image.png

切片本质是一个数组片段的描述: 包括数组指针、片段的长度、片段的容量(不改变内存分配情况下的最大长度)。

切片操作并不复制切片指向的元素,创建一个新的切片会复用原来切片的底层数组。

image.png

但是这有一个陷阱!大内存未释放!

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

比如:原切片较大,代码在原切片基础上新建小切片时、原底层数组在内存中有引用,得不到释放时,都会出现错误。

那么这时我们就可以使用 copy 替代 re-slice

性能优化 - Map

image.png

分析:

不断向 map 中添加元素的操作会触发 map 的扩容。

提前分配好空间可以减少内存拷贝和 Rehash 的消耗。

建议根据实际需求提前预估好需要的空间。

性能优化 - 字符串处理

使用strings.Builder

image.png

image.png

我们会发现使用 + 拼接性能最差,strings.Builder,bytes.Buffer 相近,strings.Buffer 更快。

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

阶段小结

本节学习了一些性能优化相关的知识,包括Benchmark、Slice、Map还有字符串处理~