Go性能调优 |青训营笔记

46 阅读3分钟

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

编程原则

简单性

  • 消除“多余的复杂性”,以简单清晰的逻辑编写代码
  • 不理解的到i吗无法修复改进

可读性

  • 代码是写给人看的,而不是机器
  • 编写维护代码的第一步是确保代码可读

生产力

  • 团队整体工作效率非常重要

编码规范-代码格式

使用gofmt自动格式化代码

编码规范-注释

  • 注释应该解释代码作用
// Open opens the named file for reading. If successful, methods on
// the returned file can be used for reading; the associated file
// descriptor has mode O_RDONLY.
// If there is an error, it will be of type *PathError.
func Open(name string) (*File, error) {
   return OpenFile(name, O_RDONLY, 0)
}
  • 注释应该解释代码如何编写
  • 注释应该解释代码实现的原因
  • 注释应该解释代码什么情况会出错

编码规范-命名规范

variable

  • 简介胜于冗余
  • 缩略词全大写,但当位于变量开头去不需要导出时,使用小写
  • 变量距离其使用的地方越远,则需要携带更多的上下文信息

function

  • 函数名不携带包名上下文信息,因为包名和函数名总是成对出现
  • 函数名尽量简短
  • 当名为foo的包某个函数返回类型Foo时,可以省略类型信息而不导致歧义
  • 当名为foo的包某个函数返回类型T(T并不是Foo)时,可以在函数名中加入类型信息

package

  • 由小写字母组成
  • 简短并包含一定的上下文信息
  • 不予标准库同名

编码规范-流程控制

  • 避免嵌套,保持正常清晰逻辑
  • 尽量保持正常代码路径为最小缩进

性能调优原则

  • 要依靠数据不是猜测
  • 要定位最大瓶颈而不是细枝末节
  • 不要过早优化
  • 不要过度优化

性能分析工具pprof

import (
"log"
"net/http"
_ "net/http/pprof" // 自动注册 pprof 的 handler 到 http server
"os"
"runtime"
"time"
)

func main() {
   log.SetFlags(log.Lshortfile | log.LstdFlags)
   log.SetOutput(os.Stdout)

   runtime.GOMAXPROCS(1)  //限制CPU使用数
   runtime.SetMutexProfileFraction(1) //开启锁调用跟踪
   runtime.SetBlockProfileRate(1) //开启阻塞调用跟踪

   go func() {
      //启动http server
      if err := http.ListenAndServe(":6060", nil); err != nil {
         log.Fatal(err)
      }
      os.Exit(0)
   }()

业务服务优化

  • 服务:能单独部署,承载一定功能的程序
  • 依赖:Service A的功能实现依赖,Service B的响应结果,称为Service A依赖Service B
  • 调用链路:能支持一个接口请求的相关服务集合及其相互之间的依赖关系
  • 基础库:公共的工具包、中间件

流程

  • 建立服务性能评估手段
  • 分析性能数据,定位性能瓶颈
  • 重点优化项改造
  • 优化效果验证

建立服务性能评估手段

服务性能评估方式

  • 单独benchmark无法满足复杂逻辑分析
  • 不同负载情况下性能表现差异

请求流量构造

  • 不同请求参数覆盖逻辑不同
  • 线上真实流量情况

压测范围

  • 单机器压测
  • 集群压测

性能数据采集

  • 单极性能数据
  • 集群性能数据