zoukankan      html  css  js  c++  java
  • pprof性能调优

    在计算机性能调试领域里,profiling 是指对应用程序的画像,画像就是应用程序使用 CPU 和内存的情况。

    Go性能优化

    • CPU profile:报告程序的 CPU 使用情况,按照一定频率去采集应用程序在 CPU 和寄存器上面的数据
    • Memory Profile(Heap Profile):报告程序的内存使用情况
    • Block Profiling:报告 goroutines 不在运行状态的情况,可以用来分析和查找死锁等性能瓶颈
    • Goroutine Profiling:报告 goroutines 的使用情况,有哪些 goroutine,它们的调用关系是怎样的

    采集性能数据

    Go语言内置了获取程序的运行数据的工具,包括以下两个标准库:

    • runtime/pprof:采集工具型应用运行数据进行分析
    • net/http/pprof:采集服务型应用运行时数据进行分析
      pprof开启后,每隔一段时间(10ms)就会收集下当前的堆栈信息,获取格格函数占用的CPU以及内存资源;最后通过对这些采样数据进行分析,形成一个性能分析报告。

    注意,我们只应该在性能测试的时候才在代码中引入pprof

    工具型应用

    CPU分析

    • 开启CPU分析:
    pprof.StartCPUProfile(w io.Writer)
    
    • 停止CPU分析
    pprof.StartCPUProfile(w io.Writer)
    

    应用执行结束后,就会生成一个文件,保存了我们的 CPU profiling 数据。得到采样数据之后,使用go tool pprof工具进行CPU性能分析。

    内存性能优化

    记录程序的堆栈信息

    pprof.WriteHeapProfile(w io.Writer)
    

    得到采样数据之后,使用go tool ppro默认是使用-inuse_space进行统计,还可以使用-inuse-objects查看分配对象的数量。

    服务型引用

    李文周博客

    具体示例

    package main
    
    import (
    	"flag"
    	"fmt"
    	"os"
    	"runtime/pprof"
    	"time"
    )
    
    // 一段有问题的代码
    func logicCode() {
    	var c chan int
    	for {
    		select {
    		case v := <-c:
    			fmt.Printf("recv from chan, value:%v
    ", v)
    		default:
    		}
    	}
    }
    
    func main() {
    	var isCPUprof bool
    	var isMemprof bool
    
    	// flag
    	flag.BoolVar(&isCPUprof, "cpu", false, "turn cpu pprof on")
    	flag.BoolVar(&isMemprof, "mem", false, "turn mem pprof on")
    	flag.Parse()
    
    	if isCPUprof {
    		file, err := os.Create("./cpu.pprof")
    		if err != nil {
    			fmt.Println("create cpu pprof failed, err: ", err)
    			return
    		}
    		pprof.StartCPUProfile(file)
    		defer func() {
    			pprof.StopCPUProfile()
    			file.Close()
    		}()
    	}
    
    	for i := 0; i < 4; i++ {
    		go logicCode()
    	}
    
    	time.Sleep(20 * time.Second)
    
    	if isMemprof {
    		file, err := os.Create("./mem.pprof")
    		if err != nil {
    			fmt.Println("create mem pprof failed, err: ", err)
    			return
    		}
    		pprof.WriteHeapProfile(file)
    		defer func() {
    			file.Close()
    		}()
    	}
    
    }
    
    
    1. go build编译后,执行pprof.exe -cpu=true命令,等待30秒会在当前目录下生成一个cpu.pprof文件
    2. 使用go工具链里的pprof来分析一下
    go tool pprof cpu.pprof
    

    执行完上面的命令会进入交互界面如下:

    C:GoProjectsgosrcgithub.comaidengtianday09pprof>go tool pprof cpu.pprof      
    Type: cpu
    Time: Jul 18, 2020 at 9:30pm (CST)
    Duration: 20.15s, Total samples = 1.13mins (336.05%)
    Entering interactive mode (type "help" for commands, "o" for options)
    (pprof)
    
    1. 在交互界面输入top3来查看程序中占用CPU前3位的函数:
    (pprof) top3
    Showing nodes accounting for 65.99s, 97.45% of 67.72s total
    Dropped 37 nodes (cum <= 0.34s)
    Showing top 3 nodes out of 9
          flat  flat%   sum%        cum   cum%
        28.72s 42.41% 42.41%     55.24s 81.57%  runtime.selectnbrecv
        26.30s 38.84% 81.25%     26.34s 38.90%  runtime.chanrecv
        10.97s 16.20% 97.45%     66.38s 98.02%  main.logicCode
    

    其中:

    • flat:当前函数占用CPU的耗时
    • flat::当前函数占用CPU的耗时百分比
    • sun%:函数占用CPU的耗时累计百分比
    • cum:当前函数加上调用当前函数的函数占用CPU的总耗时
    • cum%:当前函数加上调用当前函数的函数占用CPU的总耗时百分比
    • 最后一列:函数名称
    1. 我们还可以使用list函数名命令查看具体的函数分析,例如执行list logicCode查看我们编写的函数的详细分析。
    (pprof) list logicCode
    Total: 1.13mins
    ROUTINE ======================== main.logicCode in C:GoProjectsgosrcgithub.comaidengtianday09pprofmain.go
        10.97s   1.11mins (flat, cum) 98.02% of Total
             .          .     19:// 一段有问题的代码
             .          .     20:func logicCode() {
             .          .     21:   var c chan int
             .          .     22:   for {
             .          .     23:           select {
        10.97s   1.11mins     24:           case v := <-c:
             .          .     25:                   fmt.Printf("recv from chan, value:%v
    ", v)
             .          .     26:           default:
             .          .     27:           }
             .          .     28:   }
             .          .     29:}
    

    通过分析发现大部分CPU资源被24行占用,我们分析出select语句中的default没有内容会导致上面的case v:=<-c:一直执行。我们在default分支添加一行time.Sleep(time.Second)即可。
    5. 图形化

  • 相关阅读:
    360°视频论文调研
    360°视频相机调研
    Oculus VR眼镜调研
    VR论文调研
    3ds Max学习日记(十)——显示场景资源管理器
    最近在学习Flask框架,那么就说下jinja2吧~~~
    最近学习了Sqlite3数据库,写一下操作应用以及命令
    HTML5游戏开发,剪刀石头布小游戏案例
    jquery简单的图片切换效果,支持pc端、移动端的banner图片切换开发
    jquery简单的大背景banner图片全屏切换
  • 原文地址:https://www.cnblogs.com/lsyy2020/p/14853967.html
Copyright © 2011-2022 走看看