常见性能优化手段
- 尽可能的减少 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

- 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。自动打开浏览
器, 显示图像化界面。

图形说明
- 每个框代表一个函数,理论上框的大小越大,占用的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就可以了。

服务型程序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
网友评论