• 【博客544】golang pprof性能调试:寻找memory瓶颈


    golang pprof性能调试:寻找memory瓶颈

    1、前置

    pprof的使用与输出列解析看姐妹篇:golang pprof性能调试:寻找cpu瓶颈

    2、引入pprof到程序中,以调试memory瓶颈

    给程序加入:

    import _ "net/http/pprof"
    
    go func() {
    	  http.ListenAndServe("0.0.0.0:9999", nil)
    }()
    
    • 1
    • 2
    • 3
    • 4
    • 5

    示例:随机拼接字符串

    package main
    
    import (
    	"math/rand"
    	"net/http"
    	_ "net/http/pprof"
    )
    
    const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
    
    func randomString(n int) string {
    	b := make([]byte, n)
    	for i := range b {
    		b[i] = letterBytes[rand.Intn(len(letterBytes))]
    	}
    	return string(b)
    }
    
    func concat(n int) string {
    	s := ""
    	for i := 0; i < n; i++ {
    		s += randomString(n)
    	}
    	return s
    }
    
    func main() {
    	go func() {
    		http.ListenAndServe("0.0.0.0:9999", nil)
    	}()
    
    	for {
    		concat(100)
    	}
    }
    
    • 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

    3、pprof命令行交互式查看程序最消耗memory的地方

    1、启动上述程序:

    go run main.go
    
    • 1

    2、访问pprof暴露的memory debug api接口,收集30s内的memory数据:

    go tool pprof http://localhost:9999/debug/pprof/heap\?seconds\=30
    
    • 1

    3、在交互命令中,使用top,list来查看最消耗memory的地方

    go tool pprof http://localhost:9999/debug/pprof/heap\?seconds\=30
    Fetching profile over HTTP from http://localhost:9999/debug/pprof/heap?seconds=30
    Saved profile in /Users/zejia.lu/pprof/pprof.alloc_objects.alloc_space.inuse_objects.inuse_space.001.pb.gz
    Type: inuse_space
    Time: Nov 27, 2022 at 12:40pm (CST)
    Duration: 30s, Total samples = 1MB
    Entering interactive mode (type "help" for commands, "o" for options)
    (pprof) top
    Showing nodes accounting for -1026.68kB, 100% of 1026.68kB total
          flat  flat%   sum%        cum   cum%
      514.63kB 50.13% 50.13% -1026.68kB   100%  main.concat
      512.05kB 49.87%   100%  -512.05kB 49.87%  main.randomString
             0     0%   100% -1026.68kB   100%  main.main
             0     0%   100% -1026.68kB   100%  runtime.main
    (pprof) list main.randomString
    Total: 1MB
    ROUTINE ======================== main.randomString in /Users/zejia.lu/memory_pprof/main.go
     512.05kB  512.05kB (flat, cum) 49.87% of Total
             .          .     11:func randomString(n int) string {
             .          .     12:	b := make([]byte, n)
             .          .     13:	for i := range b {
             .          .     14:		b[i] = letterBytes[rand.Intn(len(letterBytes))]
             .          .     15:	}
     512.05kB  512.05kB     16:	return string(b)
             .          .     17:}
             .          .     18:
             .          .     19:func concat(n int) string {
             .          .     20:	s := ""
             .          .     21:	for i := 0; i < n; i++ {
    
    • 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

    4、pprof ui方式查看程序最消耗memory的地方

    1、调试时指定通过ui方式查看,ui地址为9900端口,要调试的服务暴露的pprof端口为9999:

    go tool pprof -http=":9900" http://localhost:9999/debug/pprof/heap  -inuse_objects
    
    • 1

    2、访问9900端口查看ui界面进行可视化调试:

    查看最消耗memory的地方:可以看到我们的concat逻辑函数就是memoory高消耗的地方
    在这里插入图片描述
    在这里插入图片描述

    5、pprof ui方式查看memory消耗拓扑图

    在这里插入图片描述

    6、pprof ui方式查看memory消耗火焰图

    在这里插入图片描述
    在这里插入图片描述

    7、查看其它类型的memroy,上述例子查看的是:inuse_space

    inuse_space — 已分配但尚未释放的内存空间
    inuse_objects——已分配但尚未释放的对象数量
    alloc_space — 分配的内存总量(已释放的也会统计)
    alloc_objects — 分配的对象总数(无论是否释放)
    
    • 1
    • 2
    • 3
    • 4

    8、查看所有曾经申请过的内存总量

    go tool pprof -http=":9900" http://localhost:9999/debug/pprof/allocs
    
    • 1

    结果:
    在这里插入图片描述

    9、查看消耗最多的是哪一句代码

    在这里插入图片描述

    10、如何调试其它方面的内容:

    查看程序暴露的/debug/pprof/ api

    http://127.0.0.1:9999/debug/pprof/
    
    • 1

    查看有哪些方面的调试内容:
    在这里插入图片描述

    常用调试示例:

    # 获取30秒的CPU profiling
    curl -o cpu.bin http://localhost:6060/debug/pprof/profile
    
    # 获取5秒的执行跟踪(有一定性能影响)
    curl -o trace.bin http://localhost:6060/debug/pprof/trace?seconds=5
    
    # 获取内存使用的profile
    curl -o heap.bin http://localhost:6060/debug/pprof/heap
    
    # 获取正在运行的goroutines列表
    curl -o goroutines.txt http://localhost:6060/debug/pprof/goroutine?debug=2
    
    # 获取被blocking的goroutine列表
    curl -o goroutines-blocking.txt http://localhost:6060/debug/pprof/block
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    如何分析火焰图

    火焰图的调用顺序从下到上,每个方块代表一个函数,它上面一层表示这个函数会调用哪些函数,方块的大小代表了占用 CPU 使用时长长短。

  • 相关阅读:
    Easyx介绍与安装
    【单片机毕业设计】【mcuclub-hj-015】基于单片机的水质监控的设计
    插入排序(思路分析) [数据结构][Java]
    成都优优聚美团代运营:塑造卓越优势,引领电商新时代
    Zabbix监控平台环境部署
    倒计数(来源:Google Kickstart2020 Round C Problem A)(DAY 88)
    JUC源码学习笔记1——AQS和ReentrantLock
    使用定时任务发布文章的流程
    GUI编程--PyQt5--QPushButton
    基于微信小程序的新冠疫苗预约系统 uinapp
  • 原文地址:https://blog.csdn.net/qq_43684922/article/details/128067383