性能优化 | 青训营

78 阅读2分钟

性能优化即在满足正确性、可靠性、健壮性、可读性等质量因素的前提下,设法提高程序的效率

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

    为避免内存发生拷贝,需知道最终切片的大小,预设cap的值

    原理:切片本质是一个数组片段的描述,包括了数组指针、此片段的长度和容量。切片操作是创建一个新的切片会复用切片的底层数组,更高效。

    切片属性:指针ptr、长度len、容量cap

    append时:append之后的长度<=cap:利用原底层数组剩余的空间

    append之后的长度>cap:分配一块更大的区域

    使用copy替代re-slice

    原理:在已有切片基础上进行切片,不会创建新的底层数组。如果只使用很小一段,底层数组在内存中仍占据大量空间。

  2. map预分配内存:根据实际需求提前预估好添加元素需要的空间,可以减少内存拷贝和Rehash的消耗。

  3. 使用strings.Builder进行字符串拼接:字符串拼接使用strings.Builder最快,bytes.Buffer次之,使用"+"最慢

    原理:Go中字符串为不可变类型,占用内存大小固定。

    使用”+“时,生成一个新的字符串,开辟一段新空间

    使用bytes.Buffer时,底层是[]byte数组,转化为字符串时重新申请了一块空间,存放生成的字符串变量

    使用strings.Buffer时,底层是[]byte数组,直接转化为字符串类型返回

  4. 使用空结构体节省内存:空结构体不占据内存空间,可作为占位符使用

    eg.通常用map来代替set的实现,对于集合场景,只需要用到map的键而不需要值

  5. 使用atomic包:通过硬件实现,效率更高

    原理:锁的实现是通过操作系统来实现,属于系统调用;atomic操作通过硬件实现。对于非数值,可使用atomic.Value,能承载一个interface{}。sync.Mutex不仅保护一个变量,可以用来保护一段逻辑。

  6. pptof工具:用于可视化和性能分析

分析排查:CPU问题、堆内存问题、协程问题、锁问题、阻塞问题

采样:CPU采样、堆内存采样、协程和系统线程采样、阻塞操作和锁竞争采样

  1. 业务优化流程:建立服务性能评估手段,分析性能数据、定位性能瓶颈,重点优化项改造,优化效果验证,(服务整体链路分析)

    基础库优化:适用范围更广,覆盖更多服务

    Go语言优化:(适用范围最广)优化内存分配策略、优化代码编译流程、内部压测验证、推广业务服务落地验证