go 调试利器之pprof指标分析

news2024/9/20 22:46:12

文章目录

    • 概要
    • 一、指标类型
        • 1.1、堆栈指标
        • 1.2、CPU指标分析
        • 1.3、http-pprof
    • 二、go tool pprof
        • 2.1、可视化
        • 2.2、CPU火焰图

概要

Go语言原生支持对于程序运行时重要指标或特征进行分析。pprof是其中一种重要的工具,其不仅可以分析程序运行时的错误(内存泄漏、并发冲突、协程泄漏等),也可以对程序进行优化(比如定位cpu,内存异常逻辑)。由于Go程序运行时不对外暴漏相关指标,因此Go提供了runtime/pprofnet/http/pprof基础库来与外界交互,其中net/http/pprof是对runtime/pprof的进一步封装,让用户可以通过http获取相关指标。

一、指标类型

本章节我们结合源码来看看有哪些指标提供给我们。

1.1、堆栈指标

// profiles records all registered profiles.
var profiles struct {
	mu sync.Mutex
	m  map[string]*Profile
}
//	goroutine    - stack traces of all current goroutines
//	heap         - a sampling of memory allocations of live objects
//	allocs       - a sampling of all past memory allocations
//	threadcreate - stack traces that led to the creation of new OS threads
//	block        - stack traces that led to blocking on synchronization primitives
//	mutex        - stack traces of holders of contended mutexes
func lockProfiles() {
	profiles.mu.Lock()
	if profiles.m == nil {
		// Initial built-in profiles.
		profiles.m = map[string]*Profile{
			"goroutine":    goroutineProfile,//go协程堆栈分析
			"threadcreate": threadcreateProfile,//创建新系统级线程的堆栈跟踪
			"heap":         heapProfile,//活跃对象内存分析,在应用程序进行堆分配时记录堆栈跟踪,用于监视当前和历史内存使用情况,以及检查内存泄漏
			"allocs":       allocsProfile,//过去所有内存分配的抽样,heap的结果是包含它的
			"block":        blockProfile,//导致阻塞的同步原语堆栈追踪
			"mutex":        mutexProfile,//互斥锁分析,争用互斥锁持有者的堆栈跟踪
		}
	}
}

示例

	saveFile, err := os.OpenFile("./goroutine.out", os.O_CREATE|os.O_APPEND, 0644)
	if err != nil {
		log.Println(err)
		return
	}
	err = pprof.Lookup("goroutine").WriteTo(saveFile, 0)
	if err != nil {
		log.Println(err)
	}

1.2、CPU指标分析

cpu指标分析并没有注册到全局变量到profiles.m中管理,而是需要手动开启,并在不需要采集时手动关闭。其以100hz的频率采集相关数据。

func StartCPUProfile(w io.Writer) error {
	//代码省略。。。
}
func StopCPUProfile() {
	//代码省略。。。
}

示例

	saveFile, err := os.OpenFile("./cpu.out", os.O_CREATE|os.O_APPEND, 0644)
	if err != nil {
		log.Println(err)
		return
	}
	if err = pprof.StartCPUProfile(saveFile); err != nil {
		log.Println("could not start CPU profile: ", err)
		return
	}
	//after sometime call StopCPUProfile
	defer pprof.StopCPUProfile()

runtime/pprof一般适合只跑一次的程序,下面我们看看net/http/pprof如何使用的吧。

1.3、http-pprof

http模式是最常用的,前面说过,http就是对runtime/pprof的封装,其本质也是调的runtime/pprof的函数。
下面是http模式提供的http接口。

func init() {
	http.HandleFunc("/debug/pprof/", Index)//runtime/pprof 的 profiles.m 里注册的指标
	http.HandleFunc("/debug/pprof/cmdline", Cmdline)//仅打印程序启动时的参数 
	http.HandleFunc("/debug/pprof/profile", Profile)//runtime/pprof 的StartCPUProfile/StopCPUProfile
	http.HandleFunc("/debug/pprof/symbol", Symbol)
	http.HandleFunc("/debug/pprof/trace", Trace)//runtime/trace,进行事件追踪(协程的创建,开始,结束。网络IO事件。协程阻塞事件等),属于宏观视图,具体细节还要要看pprof
}

示例

package main

import (
	"log"
	"net/http"
	_ "net/http/pprof"
	"sync"
	"time"
)

func main() {
	go testHttpPprof()
	err := http.ListenAndServe("0.0.0.0:8888", nil)
	if err != nil {
		log.Fatal(err)
	}
}
func testHttpPprof() {
	i := 0
	for {
		go Add(i)
		time.Sleep(time.Second)
		i++
	}
}

var (
	sum  = 0
	data []int
	lock sync.Mutex
)

func Add(x int) {
	defer lock.Unlock()
	if x&1 == 0 {
		time.Sleep(time.Second)
	} else {
		time.Sleep(2 * time.Second)
	}
	lock.Lock()
	sum += x
	data = append(data, sum)
}

只需要导入net/http/pprof库,再起一个http服务,就可以通过http访问相关指标了。

http://127.0.0.1:8888/debug/pprof/ #查看可用指标接口
在这里插入图片描述
http://127.0.0.1:8888/debug/pprof/heap #查看内存堆栈分析
http://127.0.0.1:8888/debug/pprof/goroutine?debug=1 #查看所有协程堆栈信息
http://127.0.0.1:8888/debug/pprof/goroutine?seconds=30 #查看30s内所有协程堆栈信息
http://127.0.0.1:8888/debug/pprof/profile?seconds=30 #查看未来30s内的CPU数据分析
依次类推…

当携带参数debug时是返回当前堆栈数据,否则返回的是一个可下载的文件
获取到文件后,可以用go tool pprof xxx来分析文件。

二、go tool pprof

这里以内存指标分析为例,首先通过http://127.0.0.1:8888/debug/pprof/heap?seconds=30获取一个pprof文件。
go tool pprof -h 可以查看所有指令
go-pprof
常用的指令:

  • top -cum #根据cum从大到小排序,默认根据flat从大到小排序。在heap分析下cum是从当前函数开始累计内存占用。flat是当前函数分配的内存,其他分析(cpu,mutex等)为维度不同的含义。
  • tree #函数调用链
  • list xxx #列出某个函数的信息

另外 heap分析有四种不同类型的内存分析维度:alloc_objects、alloc_space、inuse_objects、inuse_space
alloc_objects和inuse_objects表示申请的对象和正在使用的对象;
alloc_space和inuse_space表示申请的内存和正在使用的内存;

默认是inuse_objects,切换很简单,只需输入 alloc_objects 就能切到alloc_objects维度。

2.1、可视化

pprof提供了强大的可视化功能,可以将内容转化成图片或html,只不过需要先安装graphviz

这样在命令行中输入web,png,gif等命令就可以输出相应可视化结果。
go-pprof-ui
如图,就会生成一张个png图片。

2.2、CPU火焰图

如同2.1节,获取cpu数据文件后,除了可以用go tool pprof生成png文件外,还可以生成火焰图,命令如下:

go tool pprof -http :8889 http://127.0.0.1:8888/debug/pprof/profile?seconds=90

稍等一会就可以通过8889端口访问火焰图了(通过VIEW菜单可以切换到不同可视化方式来查看)
go-cpu火焰图
go-cpu-可视化

  • 箭头越粗代表当前路径越消耗资源(内存,时间等);
  • 箭头为虚线表示两个节点之间的某些节点已被忽略,为间接调用;
  • 节点颜色红色表示cum累计值为正数,并且很大;绿色表示cum累计值为负数,并且很大;灰色表示cum累计值可以忽略不计。

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

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

相关文章

ChatGPT 之 LangChain的文本切割方法对比

本文来自http://blog.csdn.net/hellogv/ ,引用必须注明出处! ChatGPT面向对话格式的文本理解很好,但如果要把网络上的文章让ChatGPT直接分析则会有格式的问题。文本清洗是个大课题,讲起来需要很多篇幅,优化起来前路漫…

使用arduino IDE开发ESP8266NodeMCU连接DHT11实现温湿度检测并上传onenet官网

前言: 本篇博客记录一下以arduino IDE来开发一下ESP8266NodeMCU,实现用DHT11进行温湿度检测,并且上传新版的onenet官网;我在实现这个小项目的时候,发现网上资料有关onenet的资料都是旧版的,这就有点难受了&…

[MAUI]弧形进度条与弧形滑块的交互实现

文章目录 弧形基类定义绘制弧 弧形进度条(ProgressBar)添加动画宽度补偿文本 弧形滑块(Slider)创建控制柄拖动事件处理 项目地址 进度条(ProgressBar)用于展示任务的进度,告知用户当前状态和预期; 滑块(Slider&#xf…

本地安装部署运行 ChatGLM-6B 的常见问题解答以及后续优化

报错 No module named ‘transformers_modules.THUDM/chatglm-6b’ 报错本身的意思是,没有在指定的路径THUDM/chatglm-6b找到推理用模型 一般常见于自己手动下载模型,而不是通过下边这些文件直接启动,自动下载的情况 你需要修改web_demo.py&…

分层测试终究是大梦一场空?

分层测试分了个寂寞? 分层测试这个风吹了好多年,不分层都不好意思说自己是专业测试。各互联网公司更是对此乐此不疲,测试架构、测试平台,搞了一套又一套,然而。。。 理想总是丰满,现实总是骨干&#xff0…

第十三章 反射操作相关函数

1. 【检测对象是否可被调用】callable()函数 语法参考 callable函数的语法格式如下: callable(object)参数说明: object:对象; 返回值:如果对象可调用返回 True,否则返回 False。 说明:对于…

Python 中print 和return 的区别,你了解吗?

1、print() print()函数的作用是输出数据到控制台,就是打印在你能看到的界面上。 2、return return语句[表达式]退出函数,选择性地向调用方返回一个表达式。不带参数值的return语句返回None。 return作为脚本单独运行时则需要print函数才能显示,但是…

【id:17】【1分】A. DS顺序表--类实现

题目描述 用C语言和类实现顺序表 属性包括:数组、实际长度、最大长度(设定为1000) 操作包括:创建、插入、删除、查找 类定义参考 输入 第1行先输入n表示有n个数据,即n是实际长度;接着输入n个数据 第2行输…

c语言项目——三子棋小游戏(带详细讲解解析)

1.三子棋是什么? 三子棋是一种民间传统游戏,又叫九宫棋、圈圈叉叉棋、一条龙、井字棋等。游戏分为双方对战,双方依次在9宫格棋盘上摆放棋子,率先将自己的三个棋子走成一条线就视为胜利,而对方就算输了,但是…

【MySQL 索引、事务与存储引擎】

目录 一、索引的介绍2、索引的作用3、创建索引的原刚依据(面试题) 二、索引的分类和创建1、普通索引2、唯一索引3、主键索引4、组合索引5、全文索引6、查看索引7、删除索引8、分析是否使用索引 三、MySQL事务介绍1、事务的ACID特性2、隔离性 --- 不一致的…

Linux编译器gcc/g++

文章目录 Liinux编译器gcc/g1.背景知识(程序的翻译)2.动态库、静态库 Liinux编译器gcc/g 1.背景知识(程序的翻译) 以gcc编译 以g编译,但是此时会发现没有g这个指令,所有需要安装它,安装指令 yum install gcc gcc-c gcc和g都会形成可执行文…

TransFusion:利用 Transformer 进行鲁棒性融合来进行 3D 目标检测

Query 初始化 Input-dependent 以往 Query 位置是随机生成或学习作为网络参数的,而与输入数据无关,因此需要额外的阶段(解码器层)来学习模型向真实对象中心移动的过程。 论文提出了一种基于center heatmap 的 input-dependent 初…

在 Python 中使用令牌进行 API 调用

文章目录 在 Python 中进行不带令牌的 API 调用在 Python 中使用令牌调用 API总结 当我们第一次遇到如何在 Python 中调用 API 的问题时,我们的第一个想法是,“什么是 API?”。 API是应用程序编程接口的首字母缩写; 它允许您访问…

【面试】Java并发编程

ThreadLocal ThreadLocal 为什么会导致内存泄漏 hreadLocalMap使用ThreadLocal的弱引用作为key,如果一个ThreadLocal不存在外部强引用时,Key(ThreadLocal)势必会被GC回收,这样就会导致ThreadLocalMap中key为null, 而value还存在着…

15-ajax、实现过程、封装

定义 🍿🍿🍿Async Javascript and XML 异步的JavaScript 和XML,是一种创建交互式网页应用的网页开发技术,可以在不重新加载整个网页的情况下,与服务器交换数据,并且更新部分网页 离不开 XMLH…

【C语言】万字教学,带你分步实现扫雷游戏(内含递归函数解析),剑指扫雷,一篇足矣

君兮_的个人主页 勤时当勉励 岁月不待人 C/C 游戏开发 带你轻松玩转扫雷游戏 前言一. 扫雷游戏的介绍以及内部需要实现的功能解析1.什么是扫雷游戏2.扫雷游戏所需的几个步骤 二.扫雷游戏的具体实现1.打印菜单菜单上的选择功能 2.初始化以及打印棋盘初始化函数InitBoard打印棋…

如何使用测试驱动开发(TDD)来实现100%的测试覆盖率?

本文以 DDM 为例,简单地介绍一下如何用测试驱动开发(TDD, Test-Driven Development)的方法来驱动出这个函数库。 本文以DDM为例,简单地介绍一下如何用测试驱动开发(TDD, Test-Driven Development)的方法来驱动出这个函数库。 DDM简介 DDM是…

vue-cli3的安装和项目创建

一 vue-cli3的安装 (注意:vue-cli3在安装之前,需要先删除旧版本,即vue-cli2) cnpm i -g vue/cli vue-cli3的卸载:cnpm uninstall -g vue/cli 然后用命令“vue -V”查看是否删除vue,如果没有删…

kafka原理架构深入

目录 1. 下载安装2. 命令行命令3. 概述3.1 定义3.2 基本架构 4. 架构深入4.1 生产者4.1.1 分区4.1.2 数据可靠性保证4.1.3 Exactly Once语义4.1.4 发送消息流程 4.2 broker4.2.1 日志结构4.2.2 存储策略4.2.3 Controller & ZooKeeper4.2.4 高效读写数据 4.3 消费者4.3.1 消…

模型-视图-控制器模式(MVC模式,10种常见体系架构模式之一)

、简介: 架构模式是一个通用的、可重用的解决方案,用于在给定上下文中的软件体系结构中经常出现的问题。架构模式与软件设计模式类似,但具有更广泛的范围。 模型-视图-控制器模式,也称为MVC模式。是软件工程中的一种软件架构模式&…