go 性能分析pprof和trace

news2024/12/26 3:12:54

  • runtime/pprof:采集程序(非 Server)的运行数据进行分析,用于可结束的代码块,如一次编解码操作等
  • net/http/pprof:采集 HTTP Server 的运行时数据进行分析。用于不可结束的代码块,如 web 应用等

使用场景

分析内存泄漏‘

总结

 go中的内存泄露一般都是goroutine泄露,goroutine没有被关闭,或者没有添加超时控制,让goroutine一只处于阻塞状态,不能被GC。

暂时性内存泄漏

  • 获取长字符串中的一段导致长字符串未释放
  • 获取长slice中的一段导致长slice未释放
  • 在长slice新建slice导致泄漏

永久性内存泄漏

  • goroutine泄漏
  • time.Ticker未关闭导致泄漏
  • Finalizer导致泄漏
  • Deferring Function Call导致泄漏

常见Pprof使用方式(包net/http/pprof):

1. 网络访问方式 ,go tool 查看火焰图

程序中,单独起一个协程,引入包_ "net/http/pprof" 新监听另一个端口作为pprof访问,如下图方法

func setDebug() error {
	if config.C.General.Debug != "" {
		port := strings.Split(config.C.General.Debug, ":")[1]
		log.WithFields(log.Fields{
			"profile":    "http://127.0.0.1:" + port + "/debug/pprof/profile",
			"goroutines": "http://127.0.0.1:" + port + "/goroutines",
		}).Info("open prof debug")
		go func() {
			http.HandleFunc("/goroutines", func(w http.ResponseWriter, r *http.Request) {
				num := strconv.FormatInt(int64(runtime.NumGoroutine()), 10)
				w.Write([]byte(num))
			})
			http.ListenAndServe(config.C.General.Debug, nil)
		}()
	}
	return nil
}

或者直接共用程序监听端口。引入包_ "net/http/pprof"包即可,如下

import (
"fmt"
"net/http"
_ "net/http/pprof"
)

func HelloWorld(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(w, "hello world")
}

func main() {
	http.HandleFunc("/", HelloWorld)

	err := http.ListenAndServe(":8080", nil)
	if err != nil {
		fmt.Println(err)
	}
}

先执行程序,然后再起一个终端窗口执行go tool指令。记得先安装火焰图工具,方便查看,安装方式在下方。

go tool pprof -http=:9000 http://localhost:88/debug/pprof/goroutine?debug=1(要监听的服务地址)

9000:表示你最终查看火焰图的端口,执行后会使用默认浏览器,自动打开网页

#查看所有当前goroutine的堆栈跟踪

go tool pprof http://127.0.0.1:8080/debug/pprof/goroutine

# wait 120s

go tool pprof http://127.0.0.1:8080/debug/pprof/profile?seconds=120

火焰图安装地址

下载安装可视化图形软件工具 graphviz :https://graphviz.org/download/。可自行选择Linux、Windows、Mac等对应版本,并且记得将该工具添加到系统环境变量中,否则会报错:failed to execute dot. Is Graphviz installed? Error: exec: "dot": executable file not found in %PATH% 

在这里插入图片描述

 

采集前也可以先进行压测,在压测过程中再去收集,有助于分析

  • go-wrk -c=400 -t=8 -n=100000 http://127.0.0.1:8000/api/getReq
  • 400个连接,8个线程, 模拟10w次请求

 2. gin框架,使用封装好的 

"github.com/gin-contrib/pprof"

框架里的因为封装好了。启动程序之后,可以直接浏览器访问,不需要用go tool执行了 (可以在程序开启后,先执行压测指令)

直接访问程序http://localhost:88/debug/pprof/

具体参数的含义

  • allocs: 内存分配情况的抽象情况
  • block: 阻塞堆栈的采样信息
  • cmdline: 程序启动命令及其参数
  • goroutine: 当前协程的堆栈信息
  • heap: 堆内存的采样信息
  • mutex: 锁竞争的采样信息
  • profile: cpu使用情况的采样信息
  • threadcreate: 系统程序创建情况的采样信息
  • trace: 程序运行的跟踪信息

在浏览器中我们可以看到图形化的函数调用堆栈信息。右上角的VIEW栏有一些选项,可以点开查看,Flame Graph就是传说中的火焰图。

常见Pprof使用方式(包runtime/pprof):

工具型应用调用比较简单,主要是用 runtime/pprof库,将数据写入文件中:,然后查看

package  main
import (
"flag"
"log"
"os"
"runtime/pprof"
"sync"
)

var (
	cpu string
	mem string
)

func init() {
	flag.StringVar(&cpu, "cpu", "", "write cpu profile to file")
	flag.StringVar(&mem, "mem", "", "write mem profile to file")
}

func main() {
	flag.Parse()

	//采样 CPU 运行状态
	if cpu != "" {
		f, err := os.Create(cpu)
		if err != nil {
			log.Fatal(err)
		}
		_ = pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	var wg sync.WaitGroup
	wg.Add(100)
	for i := 0; i < 100; i++ {
		go workOnce(&wg)
	}
	wg.Wait()

	//采样内存状态
	if mem != "" {
		f, err := os.Create(mem)
		if err != nil {
			log.Fatal(err)
		}
		_ = pprof.WriteHeapProfile(f)
		f.Close()
	}
}

func counter() {
	slice := make([]int, 0)
	var c int
	for i := 0; i < 10000; i++ {
		c = i + 1 + 2 + 3 + 4 + 5
		slice = append(slice, c)
	}
	_ = slice
}

func workOnce(wg *sync.WaitGroup) {
	counter()
	wg.Done()
}

go run main.go --cpu=cpu.pprof --mem=mem.pprof

go tool pprof cpu.pprof

 点击文件,打开。(前提是安装了graphviz工具)

 

 

  如果没有安装graphviz,会出现Could not execute dot;may need to install graphviz。安装graphviz的方式如下:

brew install graphviz # for macos

apt-get install graphviz # for ubuntu

yum install graphviz # for centos

trace性能工具使用

1. 使用包 "runtime/trace"

package main

import (
	"fmt"
	"log"
	"os"
	"runtime/trace"
	"sync"
)

func main() {
	//runtime.GOMAXPROCS(1)
	// 1. 创建trace持久化的文件句柄
	f, err := os.Create("trace.out")
	if err != nil {
		log.Fatalf("failed to create trace output file: %v", err)
	}
	defer func() {
		if err := f.Close(); err != nil {
			log.Fatalf("failed to close trace file: %v", err)
		}
	}()

	// 2. trace绑定文件句柄
	if err := trace.Start(f); err != nil {
		log.Fatalf("failed to start trace: %v", err)
	}
	defer trace.Stop()

	var wg sync.WaitGroup
	wg.Add(2)

	go func() {
		fmt.Println(`Hello`)
		wg.Done()
	}()

	go func() {
		fmt.Println(`World`)
		wg.Done()
	}()

	wg.Wait()
}

先开窗口执行

go run main.go

再打开一个窗口执行

 go tool trace -http=localhost:8080  trace.out

2023/01/03 11:01:57 Parsing trace...
2023/01/03 11:01:57 Splitting trace...
2023/01/03 11:01:57 Opening browser. Trace viewer is listening on http://127.0.0.1:8888

 View trace:查看跟踪
Goroutine analysis:Goroutine 分析,查看具体的携程数
Network blocking profile:网络阻塞概况
Synchronization blocking profile:同步阻塞概况
Syscall blocking profile:系统调用阻塞概况
Scheduler latency profile:调度延迟概况,这个是常用的,用来分析耗时在哪里
User defined tasks:用户自定义任务
User defined regions:用户自定义区域
Minimum mutator utilization:最低 Mutator 利用率

参考:

Go语言内存泄露_cqu_jiangzhou的博客-CSDN博客_go内存泄露

http://liumurong.org/2019/12/gin_pprof/

Go pprof 性能分析工具 - 详细使用图解:_dreamer'~的博客-CSDN博客_pprof图怎么看

golang性能分析之trace_raoxiaoya的博客-CSDN博客_golang trace

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/136124.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

​工程师如何对待开源

工程师如何对待开源 本文是笔者作为一个在知名科技企业内从事开源相关工作超过 20 年的工程师&#xff0c;亲身经历或者亲眼目睹很多工程师对待开源软件的优秀实践&#xff0c;也看到了很多 Bad Cases&#xff0c;所以想把自己的一些心得体会写在这里&#xff0c;供工程师进行…

linux的shell的概述

Shell 教程 Shell 是一个用 C 语言编写的程序&#xff0c;它是用户使用 Linux 的桥梁。Shell 既是一种命令语言&#xff0c;又是一种程序设计语言。 Shell 是指一种应用程序&#xff0c;这个应用程序提供了一个界面&#xff0c;用户通过这个界面访问操作系统内核的服务。 Ke…

各种颜色的代码

颜色代码对照表如下&#xff1a; 关于16进制颜色代码&#xff1a; 这有必要了解一颜色系统的概念&#xff1a; RGB&#xff1a;RGB色彩模式是工业界的一种颜色标准&#xff0c;是通过对红(R)、绿(G)、蓝(B)三个颜色通道的变化以及它们相互之间的叠加来得到各式各样的颜色的&a…

MySQL的一些有意思的指令和函数

这个里面我准备记录一些比较有意思的MySQL的指令和函数&#xff0c;当然使用函数的时候我们要注意&#xff0c;会不会因为函数导致不走索引&#xff0c;走全表扫描的情况。 因为对索引字段做函数操作&#xff0c;可能会破坏索引值的有序性&#xff0c;因此优化器就决定放弃走树…

文本分类(LSTM+PyTorch)

本文的配套代码已上传至github&#xff0c;链接在文末&#xff0c;同时附带中文数据集。 一、传统方法的基本步骤 预处理&#xff1a;首先进行分词&#xff0c;然后是除去停用词&#xff1b;将文本表示成向量&#xff0c;常用的就是文本表示向量空间模型&#xff1b;进行特征…

回调函数、qsort函数、sort函数与lambda表达式

目录 目录 1、回调函数 2、sort函数 3、lambda表达式 4、qsort与sort函数使用lambda表达式 1、回调函数 回调函数就是一个通过函数指针调用的函数。如果你把函数的指针&#xff08;地址&#xff09;作为参数传递给另一 个函数&#xff0c;当这个指针被用来调用其所指向的函…

凝心聚力 开源共建 | 统信软件参与成立OpenKunlun开源固件社区

11月22日&#xff0c;统信软件携手国内固件厂商、处理器厂商、外设板卡厂商等数十家产业同仁参与共建的OpenKunlun开源固件社区正式成立&#xff01; OpenKunlun社区是在自愿、开源、平等和协作的基础上&#xff0c;由基础软硬件企业、高等院校、个人开发者共同参与的非营利性开…

STM32——STM32中断系统与EXTI外部中断

文章目录一、中断系统二、STM32中断系统三、NVIC&#xff08;嵌套中断向量控制器&#xff09;NVIC基本结构NVIC优先级分组四、EXTI&#xff08;外部中断&#xff09;EXTI简介EXTI基本结构AFIO复用IO口EXTI框图五、对射式红外传感器计次电路设计关键函数EXTI库函数文件&#xff…

SpringMVC与SpringBoot响应请求的流程

SpringMVC是基于Servlet的MVC模型&#xff0c;Model&#xff1a;一个或多个javabean对象&#xff0c;用于存储数据和业务逻辑&#xff1b;View&#xff1a;一个或多个jsp页面&#xff0c;拿到控制器提交的数据为模型提供数据显示&#xff1b;Controller&#xff1a;一个或多个s…

【消息中间件】RabbitMQ的工作模式

前 言 &#x1f349; 作者简介&#xff1a;半旧518&#xff0c;长跑型选手&#xff0c;立志坚持写10年博客&#xff0c;专注于java后端 ☕专栏简介&#xff1a;深入、全面、系统的介绍消息中间件 &#x1f330; 文章简介&#xff1a;本文将介绍RabbitMQ的工作模式 &#x1f353…

cubeIDE开发, stm32的CRC计算CubeMX配置及HAL库底层实现分析

一、stm32的CRC 1.1 CRC的简介及MCU关联说明 STM32的CRC(Cyclic Redundancy Check&#xff0c;循环冗余校验)计算单元使用一个固定的多项式发生器&#xff0c;从一个32位的数据字产生一个CRC码。在业务开发应用中&#xff0c;会基于CRC的技术用于验证数据传输或存储完整性。在E…

【python基础_05】面向对象1_对象和类、魔术方法

文章目录1. 类和对象1.1 使用对象组织数据的模版1.2 成员变量和成员方法1.3 实现代码2. 内置方法&#xff08;魔术方法&#xff09;2.1 构造方法&#xff1a; __init__()2.2 __call__()2.3 __len__()2.3 __str__()2.4 __getitem__()2.5 __setitem__()2.6 __delitem__()2.7 __lt…

【从零开始学习深度学习】35. 门控循环神经网络之门控循环单元(gated recurrent unit,GRU)介绍、Pytorch实现GRU并进行训练预测

在循环神经网络中&#xff0c;当时间步数较大或者时间步较小时&#xff0c;循环神经网络的梯度较容易出现衰减或爆炸。上一篇文章中介绍的裁剪梯度可以应对梯度爆炸&#xff0c;但无法解决梯度衰减的问题。因此&#xff0c;循环神经网络在实际中较难捕捉时间序列中时间步距离较…

Elastic-Job分布式任务调度(1):概述

1 什么是任务调度 我们可以先思考一下下面业务场景的解决方案&#xff1a; 某电商系统需要在每天上午10点&#xff0c;下午3点&#xff0c;晚上8点发放一批优惠券。某银行系统需要在信用卡到期还款日的前三天进行短信提醒。某财务系统需要在每天凌晨0:10结算前一天的财务数据…

【自学Python】Linux安装Python

Linux安装Python Python下载 Python下载地址 https://www.python.org/ftp/python/3.7.4/Python-3.7.4.tar.xzPython下载 我们在 Linux 终端中&#xff0c;直接使用 wget 命令&#xff0c;下载 Linux 版 Python 的安装包&#xff0c;我们在终端输入以下命令&#xff1a; wg…

PAT乙级|1094 谷歌的招聘

题源https://pintia.cn/problem-sets/994805260223102976/exam/problems/1071785997033074688 提交1&#xff1a;一个用例没过 提交2&#xff1a;AC 错因&#xff1a;输出需为字符串&#xff0c;例如在 200236 中找 4 位素数&#xff0c;解是0023 关键&#xff1a;第33行代码…

linphone android sdk 源码下载编译

前言 前面的有写过Android 使用Linphone SDK开发SIP客户端相关的文章, 在后续的开发过程中, 为了更深入了解linphone, 便尝试下载SDK源码自行编译. 关于linphone这里不作过多介绍, 可以参考前面的文章. Linphone-SDK 是一个将 Liblinphone 及其依赖项捆绑为 git 子模块的项目&a…

HTC FOCUS3在PC端串流FOHEART H1数据手套(手柄)

本教程介绍使用FOHEART H1数据手套与HTC手柄驱动VR中的虚拟手运动&#xff0c;实现手部的追踪及定位。 本教程内容与之前使用腕带定位&#xff08;HTC FOCUS3在PC端串流FOHEART H1数据手套&#xff08;腕带&#xff09;&#xff09;不同&#xff0c;这次我们使用头显中自带的…

【Kuangbin简单DP】挤奶时间

4561. 挤奶时间 - AcWing题库 题意&#xff1a; 思路&#xff1a; 一开始的思路是把这么多的区间当作物品&#xff0c;然后选与不选&#xff0c;这样去搞线性DP 显然是不行的&#xff0c;因为这样答案就不知道怎么统计了 而且&#xff0c;我们是设阶段&#xff01;&#xf…

HSK汉语考试变革,您需要了解以下几点

2023年HSK考试可能有哪些变化汉语考试难度增加了还是减低了&#xff1f; 对现在的课程和教材有影响&#xff1f; 汉语老师怎么样应对&#xff1f;HSK考试变化猜想1.HSK3级考试和HSKK初级结合在一起 2.HSK4级考试和HSKK中级结合在一起 3.HSK5,6级考试和HSKK高级结合在一起HSKK考…