性能优化即在满足正确性、可靠性、健壮性、可读性等质量因素的前提下,设法提高程序的效率
-
slice预分配内存:在尽可能的情况下,在使用make()初始化切片时提供容量信息。
为避免内存发生拷贝,需知道最终切片的大小,预设cap的值
原理:切片本质是一个数组片段的描述,包括了数组指针、此片段的长度和容量。切片操作是创建一个新的切片会复用切片的底层数组,更高效。
切片属性:指针ptr、长度len、容量cap
append时:append之后的长度<=cap:利用原底层数组剩余的空间
append之后的长度>cap:分配一块更大的区域
使用copy替代re-slice
原理:在已有切片基础上进行切片,不会创建新的底层数组。如果只使用很小一段,底层数组在内存中仍占据大量空间。
-
map预分配内存:根据实际需求提前预估好添加元素需要的空间,可以减少内存拷贝和Rehash的消耗。
-
使用strings.Builder进行字符串拼接:字符串拼接使用strings.Builder最快,bytes.Buffer次之,使用"+"最慢
原理:Go中字符串为不可变类型,占用内存大小固定。
使用”+“时,生成一个新的字符串,开辟一段新空间
使用bytes.Buffer时,底层是[]byte数组,转化为字符串时重新申请了一块空间,存放生成的字符串变量
使用strings.Buffer时,底层是[]byte数组,直接转化为字符串类型返回
-
使用空结构体节省内存:空结构体不占据内存空间,可作为占位符使用
eg.通常用map来代替set的实现,对于集合场景,只需要用到map的键而不需要值
-
使用atomic包:通过硬件实现,效率更高
原理:锁的实现是通过操作系统来实现,属于系统调用;atomic操作通过硬件实现。对于非数值,可使用atomic.Value,能承载一个interface{}。sync.Mutex不仅保护一个变量,可以用来保护一段逻辑。
-
pptof工具:用于可视化和性能分析
分析排查:CPU问题、堆内存问题、协程问题、锁问题、阻塞问题
采样:CPU采样、堆内存采样、协程和系统线程采样、阻塞操作和锁竞争采样
-
业务优化流程:建立服务性能评估手段,分析性能数据、定位性能瓶颈,重点优化项改造,优化效果验证,(服务整体链路分析)
基础库优化:适用范围更广,覆盖更多服务
Go语言优化:(适用范围最广)优化内存分配策略、优化代码编译流程、内部压测验证、推广业务服务落地验证