golang 性能优化之路
一、性能分析手段
1. pprof 性能分析: \笔记\golang\go 性能分析工具 pprof
二、优化 CPU 耗时
通过分析 cpu.pprof ,找到耗时比较多(颜色比较深)的函数,优化该函数
优化 | 替换 | 备注 |
---|---|---|
fmt.XXX | 减少使用 | fmt 的存在一定的耗时 |
正则匹配 | 字符串切割规则匹配 | 正则匹配的性能非常低 |
map 使用 | 可以替换为 slice,索引时间更快 | 数据量大的情况下,map 的索引速度远不及 slice 的下标索引 |
内存分配 | 减少 map、slice 的频繁分配内存,可先预分配 | 频繁进行 slice 和 map 内存分配,耗时严重 |
反射 | 减少使用反射 | 反射的性能极低 |
字符串拼接 | strings.Builder | 减少使用 +、fmt 等拼接方式,推荐使用 strings.Builder |
插入数据库 | 避免循环创建数据,应该批量创建 | 批量创建时需要控制条数,避免超时或 oom |
三、优化内存
mem.pprof 目前看起来鸡肋,还不如直接运行程序,任务管理器/linux top 直接查看查询的运行内存的情况
优化 | 替换 | 备注 |
---|---|---|
内存泄漏 | 如文件未关闭、协程泄漏等 | |
全量加载数据 | 避免全量加载数据到内存,如 1. 文件全量读取可以优化为流式读取; 2. 查询数据库数据应该添加 limit 校验避免全查; 3. 批量创建数据时,应该设置适当的条数,分批创建,而不是全量加载后再进行分配创建; 4. 某些计算场景可以使用内存复用而不是额外分配内存,比如判断元素是否存在数组中时,常规做法是数组先 map 化,然后判断,其实可以进行循环遍历数组进行判断,减少 map 的分配 5. 可以适当使用指针,而不是副本,比如当一些 slice 需要 map 化时,map 的 val 可以是 slice 元素的指针而不是副本 |
|