Cwww3's Blog

Record what you think

0%

pprof

pprof

部署

  • web程序
1
2
3
import (
_ "net/http/pprof" // 引入 pprof 包
)
1
2
3
4
5
main() {
...
fmt.Println(http.ListenAndServe("localhost:port", nil))
...
}
  • 对于非web程序
1
2
3
4
5
6
7
8
// 通过启动一个goroutine监听端口
main() {
...
go func() {
fmt.Println(http.ListenAndServe("localhost:port", nil))
}()
...
}
1
2
3
4
// 或者使用runtime/pprof包 并从程序中获取相关信息
import (
_ "runtime/pprof" // 引入 pprof 包
)

采集信息

  • 接口获取

通过访问 http://localhost:port/debug/pprof/采集数据

1
2
3
4
# 对 CPU 的信息采集三秒,然后输出到 cpu.pprof 文件中
curl http://localhost:port/debug/pprof/profile?seconds=3 -o cpu.pprof
# 等价
curl http://localhost:port/debug/pprof/profile?seconds=3 > cpu.pprof
  • 程序中获取
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// 获取 trace 信息
f, err := os.Create("trace.out")
if err != nil {
panic(err)
}

err = trace.Start(f)
if err != nil {
panic(err)
}


// 获取 CPU 的信息
var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to `file`")
flag.Parse()
if *cpuprofile != "" {
f, err := os.Create(*cpuprofile)
if err != nil {
log.Fatal("could not create CPU profile: ", err)
}
defer f.Close()
if err := pprof.StartCPUProfile(f); err != nil {
log.Fatal("could not start CPU profile: ", err)
}
defer pprof.StopCPUProfile()
}

// 获取内存信息
var memprofile = flag.String("memprofile", "", "write memory profile to `file`")
if *memprofile != "" {
f, err := os.Create(*memprofile)
if err != nil {
log.Fatal("could not create memory profile: ", err)
}
defer f.Close()
runtime.GC()
if err := pprof.WriteHeapProfile(f); err != nil {
log.Fatal("could not write memory profile: ", err)
}
}

  • 测试产生
1
go test -bench . -cpuprofile cpu.prof

视化分析

go tool pprof 既可以对采集到的离线数据进行分析,也可以是结合上面的 pprof http 接口,直接在线上进行分析

  • 在线分析
1
2
# 交互式界面
go tool pprof http://localhost:port/debug/pprof/heap
  • 离线分析
1
2
3
4
# 交互式界面
go tool pprof memory.prof
# 以web形式打开
go tool pprof -http=:port memory.prof

go tool trace 无法在线上完成,只能通过线下的方式完成

  • 离线分析
1
go tool trace trace.out

压测工具

1
2
3
4
5
6
7
git clone https://github.com/wg/wrk
cd wrk
# 默认情况下wrk会使用自带的LuaJIT和OpenSSL,
# 如果你想使用系统已安装的版本,可以使用WITH_LUAJIT和WITH_OPENSSL这两个选项来指定它们的路径
# make WITH_LUAJIT=/usr WITH_OPENSSL=/usr
make
# 在当前目录生成wrk二进制文件 可以将其拷贝到$PATH目录下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 使用方法: wrk <选项> <被测HTTP服务的URL>                            
Options:
-c, --connections <N> 跟服务器建立并保持的TCP连接数量
-d, --duration <T> 压测时间
-t, --threads <N> 使用多少个线程进行压测

-s, --script <S> 指定Lua脚本路径
-H, --header <H> 为每一个HTTP请求添加HTTP头
--latency 在压测结束后,打印延迟统计信息
--timeout <T> 超时时间
-v, --version 打印正在使用的wrk的详细版本信息

<N>代表数字参数,支持国际单位 (1k, 1M, 1G)
<T>代表时间参数,支持时间单位 (2s, 2m, 2h)

# 使用8个线程200个连接,对bing首页进行了30秒的压测,并要求在压测结果中输出响应延迟信息
wrk -t8 -c200 -d30s --latency "http://www.bing.com"
Donate comment here.