Golang程序如何查找内存泄漏(pprof)

 更新时间:2024年12月20日 10:52:58   作者:守望先锋第一亚索  
该文章详细介绍了如何使用Golang的pprof工具查找内存泄漏,首先,在main包中引入pprof包并设置条件编译,然后编译程序并运行,通过执行gotoolpprof-inuse_space命令,可以进入交互模式并使用top命令查看内存分配最多的函数,如果本机中有源代码

Golang程序查找内存泄漏

1. 在main包中

选择在一个单独文件中加上pprof包引用并设置条件编译,这样不会与develop正式版本代码产生任何耦合。

// +build debug

package main

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

func init() {
	go http.ListenAndServe(":18080", nil)
}

2. 编译

 go build -tags debug .

3. 在目标机中运行刚编译出来的debug版本程序

本例中ip为随意编写的。

4. 执行

go tool pprof -inuse_space http://192.168.20.5:18080/debug/pprof/heap进入交互模式:

[user@LAPTOP-LCP testtool]$ go tool pprof -inuse_space http://192.168.20.5:18080/debug/pprof/heap
Fetching profile over HTTP from http://192.168.20.5:18080/debug/pprof/heap
Saved profile in C:\Users\Noname\pprof\pprof.testtool.alloc_objects.alloc_space.inuse_objects.inuse_space.006.p
b.gz
File: testtool
Type: inuse_space
Time: Aug 16, 2022 at 2:24pm (CST)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top 10
Showing nodes accounting for 27831.78kB, 100% of 27831.78kB total
Showing top 10 nodes out of 35
flat flat% sum% cum cum%
11787.50kB 42.35% 42.35% 11787.50kB 42.35% runtime.allocm
9382.95kB 33.71% 76.07% 9382.95kB 33.71% io.ReadAll
2561.02kB 9.20% 85.27% 2561.02kB 9.20% runtime.malg
1536.21kB 5.52% 90.79% 1536.21kB 5.52% github.com/aws/aws-sdk-go/aws/endpoints.init
514kB 1.85% 92.63% 514kB 1.85% bufio.NewReaderSize
514kB 1.85% 94.48% 514kB 1.85% bufio.NewWriterSize
512.08kB 1.84% 96.32% 512.08kB 1.84% net/http.newTransferWriter
512.02kB 1.84% 98.16% 512.02kB 1.84% runtime.gcBgMarkWorker
512kB 1.84% 100% 512kB 1.84% runtime.doaddtimer
0 0% 100% 9382.95kB 33.71% io/ioutil.ReadAll
(pprof)
(pprof)

交互界面使用top命令查看内存分配最多的函数。

如果本机中有源代码,可以使用list命令查看源代码中哪一行分配的函数最多。

(pprof)
(pprof) list io.ReadAll
Total: 27.18MB
ROUTINE ======================== io.ReadAll in C:\Program Files\Go\src\io\io.go
9.16MB 9.16MB (flat, cum) 33.71% of Total
. . 626:func ReadAll(r Reader) ([]byte, error) {
. . 627: b := make([]byte, 0, 512)
. . 628: for {
. . 629: if len(b) == cap(b) {
. . 630: // Add more capacity (let append pick how much).
9.16MB 9.16MB 631: b = append(b, 0)[:len(b)]
. . 632: }
. . 633: n, err := r.Read(b[len(b):cap(b)])
. . 634: b = b[:len(b)+n]
. . 635: if err != nil {
. . 636: if err == EOF {
(pprof)
(pprof)

5. 也可以使用以下命令直接导出调用图

非常直观(需要安装Graphviz,详询Download | Graphviz

go tool pprof -inuse_space -png http://192.168.20.5:18080/debug/pprof/heap > heap.png

可以在图片中直观地看到,调用过程中每个函数的内存使用占比。

出现内存泄漏时,如果只查看一次很难确定真正出现内存泄露的代码位置,可以在程序运行一段时间后,程序出现内存泄露已经很明显后,再次查看内存占用分析图,找到两张图中内存占用比例相差最大的函数。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • go:gin输出日志文件方式

    go:gin输出日志文件方式

    这篇文章主要介绍了go:gin输出日志文件方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • Golang设计模式之适配器模式介绍和代码示例

    Golang设计模式之适配器模式介绍和代码示例

    适配器是一种结构型设计模式, 它能使不兼容的对象能够相互合作,可担任两个对象间的封装器, 它会接收对于一个对象的调用, 并将其转换为另一个对象可识别的格式和接口,本文将通过代码示例详细给大家介绍Golang的适配器模式
    2023-06-06
  • go语言实现AES加密的方法

    go语言实现AES加密的方法

    这篇文章主要介绍了go语言实现AES加密的方法,实例分析了Go语言的加密技巧,需要的朋友可以参考下
    2015-03-03
  • GoFrame glist 基础使用和自定义遍历

    GoFrame glist 基础使用和自定义遍历

    这篇文章主要为大家介绍了GoFrame glist的基础使用和自定义遍历示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • Go语言的互斥锁的详细使用

    Go语言的互斥锁的详细使用

    本文主要介绍了Go语言的互斥锁的详细使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-06-06
  • Go实现socks5服务器的方法

    Go实现socks5服务器的方法

    SOCKS5 是一个代理协议,它在使用TCP/IP协议通讯的前端机器和服务器机器之间扮演一个中介角色,使得内部网中的前端机器变得能够访问Internet网中的服务器,或者使通讯更加安全,这篇文章主要介绍了Go实现socks5服务器的方法,需要的朋友可以参考下
    2023-07-07
  • 使用go操作redis的有序集合(zset)

    使用go操作redis的有序集合(zset)

    这篇文章主要介绍了使用go操作redis的有序集合(zset),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • go local history本地历史恢复代码神器

    go local history本地历史恢复代码神器

    这篇文章主要为大家介绍了go local history本地历史恢复代码神器的使用功能详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2024-01-01
  • Go语言中XML文件的读写操作

    Go语言中XML文件的读写操作

    本文主要介绍了Go语言中XML文件的读写操作,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • Golang sync.Map原理深入分析讲解

    Golang sync.Map原理深入分析讲解

    go中map数据结构不是线程安全的,即多个goroutine同时操作一个map,则会报错,因此go1.9之后诞生了sync.Map,sync.Map思路来自java的ConcurrentHashMap
    2022-12-12

最新评论