美文网首页
Go程序性能优化

Go程序性能优化

作者: 强某某 | 来源:发表于2020-08-06 10:17 被阅读0次

常见性能优化手段

  • 尽可能的减少 HTTP 的请求数。合并css和js以及图片。
  • 使用CDN系统,实现就近访问。
  • 启用gzip压缩,降低网页传输的大小。
  • 优化后端api服务的性能。

Api服务性能优化的目标

  • 线上程序是一个黑盒
  • 通过性能优化,能够分析程序占用了多少资源?
  • 找到系统的瓶颈点

Golang中的性能优化方式

  • Cpu维度的优化
  • Mem(内存)维度的优化
  • 锁竞争维度的优化

性能优化背景以及原理

  • 要知道程序占用了多少资源,比如Cpu、内存等
  • 要知道程序的各个函数占用的资源比例
  • 有了上面两个部分数据,我们就可以快速的定位到系统的性能瓶颈
  • 怎么达成这个目标?

当pprof开启后,每隔一段时间(10ms)收集下当前堆栈信息,获取各
个函数占用的cpu以及内存资源;当pprof完成之后,通过对这些采
样数据进行分析。形成一个性能分析报告

CPU性能优化

  • import (“runtime/pprof”)
  • 开始CPU性能分析:pprof.StartCPUProfile(w io.Writer)
  • 停止CPU性能分析: pprof.StopCPUProfile()
package main

import (
    "flag"
    "fmt"
    "os"
    "runtime/pprof"
    "time"
)

func logicCode() {
    var c chan int // = make(chan int, 1)
    for {
        select {
        case v := <-c:
            fmt.Printf("read from chan, v:%v\n", v)
        default:
        }
    }
}
func main() {
    var isCpuPprof bool
    flag.BoolVar(&isCpuPprof, "cpu", false, "turn cpu pprof on")
    flag.Parse()
    if isCpuPprof {
        file, err := os.Create("C:/tmp/cpu.pprof")
        if err != nil {
            fmt.Printf("create cpu pprof failed, err:%v\n", err)
            return
        }
        pprof.StartCPUProfile(file)
        defer pprof.StopCPUProfile()
    }
    for i := 0; i < 8; i++ {
        go logicCode()
    }
    time.Sleep(30 * time.Second)
}

CPU性能优化实战

  • 生成的采样数据,存储在当面目录下,./cpu.pprof
  • 使用命令进行分析, go tool pprof ./cpu_pprof_exam.exe ./cpu.pprof
  • 使用topN命令列出cpu消耗前几的函数,比如: top3
1.jpg
  • flat: 当前函数消耗的Cpu耗时,%flat:当前函数消耗的Cpu耗时总占比。
  • sum%: 函数消耗的Cpu耗时的累计占比。
  • cum: 当前函数加上调用当前函数的函数消耗的Cpu耗时之和。Cum%:消耗的cpu总占比

图像化界面

  • 安装graphviz图形化工具,https://graphviz.gitlab.io/_pages/Download/Download_windows.html
  • 安装完了之后,把安装路径加入到环境变量的PATH路径中。比如:C:\Program Files
    (x86)\Graphviz2.38\bin
  • go tool pprof ./cpu_pprof_exam.exe ./cpu.pprof,进入交互模式,敲入web。自动打开浏览
    器, 显示图像化界面。
2.jpg

图形说明

  • 每个框代表一个函数,理论上框的大小越大,占用的cpu资源越多。
  • 方框之间的线条,代表函数之间调用关系。
  • 线条上的数字,反映函数调用的次数。
  • 方框中的第一行数字,代表当前函数占用的cpu比例;第二行数字代表当前函数累计的比例

Cpu pprof和单元测试结合

  • 每次都手动导入pprof比较麻烦,可以直接用gotest压力测试时进行pprof。
  • 先编译压力测试程序,比如 go test –c 生成xxx_test可执行程序。
  • 分析cpu性能:./xxx.test –test.bench=xxxx–test.cpuprofile=./cpu.pprof。
  • 分析内存: ./xxx.test –test.bench=xxxx–test.memprofile=./mem.pprof

MEM性能优化

  • import (“runtime/pprof”)
  • 启用内存优化分析:pprof.WriteHeapProfile(w io.Writer)
  • 使用go tool pprof进行内存分析
  • tips go tool pprof默认是使用—inuse_space进行统计,可以使用—inuse-objects查看分配的数量。

火焰图生成

  • 火焰图是Bredan Gregg创建一种性能分析图表。
  • 同样,go pprof的数据也可以转化成火焰图。
  • 使用Uber提供的: https://github.com/uber/go-torch 的工具。

go-torch安装

  • go get github.com/uber/go-torch 。
  • git clone https://github.com/brendangregg/FlameGraph.git
  • 把FlameGraph目录加入到操作系统的环境变量 PATH中。
  • 安装perl环境支持,http://www.perl.org/get.html
  • Windows的同学,需要把go-torch/render/flamegraph.go的GenerateFlameGraph改成如下代码, 并在go-torch目录下执行go install就可以了
func GenerateFlameGraph(graphInput []byte, args ...string) ([]byte, error) {
    flameGraph := findInPath(flameGraphScripts)
    if flameGraph == "" {
        return nil, errNoPerlScript
    }
    if runtime.GOOS == "windows" {
        return runScript("perl", append([]string{flameGraph}, args...), graphInput)
    }
    return runScript(flameGraph, args, graphInput)
}

go-torch使用: 把 go tool pprof 换成 go-torch就可以了。

3.jpg

服务型程序pprof

原声http以及tcp相关后台型程序pprof

  • 一直在后台运行,如果线上出现了性能问题怎么办?
  • Golang标准库:import _ "net/http/pprof"。
  • 打开url: http://localhost:xxx/debug/pprof/,就能看到pprof相关的信息。
  • 基础使用
    • /debug/pprof/profile, 访问这个连接,会自动进行cpu pprof, 并把分析数据下载。
    • /debug/pprof/heap,访问这个连接,会自动进行mem,pprof, 并把分析数据下载。
    • /debug/pprof/goroutines,访问这个连接,会把当前程序的goroutes信息打印出来。
    • /debug/pprof/threadcreate,访问这个连接,会把当前程序的使用的操作系统线程数量打印出来。

使用gin框架的后台型程序pprof

  • import (“github.com/DeanThompson/ginpprof”)
  • go get github.com/DeanThompson/ginpprof
  • 打开url: http://localhost:xxx/debug/pprof/,就能看到pprof相关的信息

补充: https://github.com/pingguoxueyuan/gostudy/tree/master/listen30

相关文章

网友评论

      本文标题:Go程序性能优化

      本文链接:https://www.haomeiwen.com/subject/wxhzrktx.html