关于Go语言MemoryProfile的一些问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于Go语言MemoryProfile的一些问题相关的知识,希望对你有一定的参考价值。

关于如何使用pprof进行profiling的问题,请参考https://studygolang.com/articles/7069,本文仅做一些补充。

 

  1. http://xxx:6060/debug/pprof/heap?debug=1页面的解释

heap profile: 219: 286339776 [29791: 2945785336] @ heap/1048576

其中 219 —— 当前快照中看到的尚存活的堆对象的数量
   286339776 —— 当前快照中看到的尚存活的堆对象的字节数
  29791 —— 当前快照中看到的分配过的堆对象(包括已经释放的)的数量

  29791 —— 当前快照中看到的分配过的堆对象(包括已经释放的)的字节数
   1048576 —— MemProfileRate * 2

对于每个具体的对象,数据格式为
8: 62062592 [12: 93093888] @ 0x8fd38f 0x8fe4fa 0x8fa5f0 0x90714e 0x909b36 0x46bc31

其中, 8 —— 当前callstack上尚存活的对象数
   62062592 —— 当前callstack上尚存活的对象占用字节数
   12 —— 当前callstack上总过分配过的(包括已释放的)对象数
   93093888 ——当前callstack上总过分配过的(包括已释放的)对象占用的字节数
   @后面的内容 —— 当前callstack的栈帧,和下面解析的的callstack一致


这些内容都是在pprof.go文件中输出的,具体参看代码
	fmt.Fprintf(w, "heap profile: %d: %d [%d: %d] @ heap/%d\n",
		total.InUseObjects(), total.InUseBytes(),
		total.AllocObjects, total.AllocBytes,
		2*runtime.MemProfileRate)

	for i := range p {
		r := &p[i]
		fmt.Fprintf(w, "%d: %d [%d: %d] @",
			r.InUseObjects(), r.InUseBytes(),
			r.AllocObjects, r.AllocBytes)
		for _, pc := range r.Stack() {
			fmt.Fprintf(w, " %#x", pc)
		}
		fmt.Fprintf(w, "\n")
		printStackRecord(w, r.Stack(), false)
	}

	// Print memstats information too.
	// Pprof will ignore, but useful for people
	s := new(runtime.MemStats)
	runtime.ReadMemStats(s)
	fmt.Fprintf(w, "\n# runtime.MemStats\n")
	fmt.Fprintf(w, "# Alloc = %d\n", s.Alloc)
	fmt.Fprintf(w, "# TotalAlloc = %d\n", s.TotalAlloc)
	fmt.Fprintf(w, "# Sys = %d\n", s.Sys)
	fmt.Fprintf(w, "# Lookups = %d\n", s.Lookups)
	fmt.Fprintf(w, "# Mallocs = %d\n", s.Mallocs)
	fmt.Fprintf(w, "# Frees = %d\n", s.Frees)

	fmt.Fprintf(w, "# HeapAlloc = %d\n", s.HeapAlloc)
	fmt.Fprintf(w, "# HeapSys = %d\n", s.HeapSys)
	fmt.Fprintf(w, "# HeapIdle = %d\n", s.HeapIdle)
	fmt.Fprintf(w, "# HeapInuse = %d\n", s.HeapInuse)
	fmt.Fprintf(w, "# HeapReleased = %d\n", s.HeapReleased)
	fmt.Fprintf(w, "# HeapObjects = %d\n", s.HeapObjects)

	fmt.Fprintf(w, "# Stack = %d / %d\n", s.StackInuse, s.StackSys)
	fmt.Fprintf(w, "# MSpan = %d / %d\n", s.MSpanInuse, s.MSpanSys)
	fmt.Fprintf(w, "# MCache = %d / %d\n", s.MCacheInuse, s.MCacheSys)
	fmt.Fprintf(w, "# BuckHashSys = %d\n", s.BuckHashSys)
	fmt.Fprintf(w, "# GCSys = %d\n", s.GCSys)
	fmt.Fprintf(w, "# OtherSys = %d\n", s.OtherSys)

	fmt.Fprintf(w, "# NextGC = %d\n", s.NextGC)
	fmt.Fprintf(w, "# LastGC = %d\n", s.LastGC)
	fmt.Fprintf(w, "# PauseNs = %d\n", s.PauseNs)
	fmt.Fprintf(w, "# PauseEnd = %d\n", s.PauseEnd)
	fmt.Fprintf(w, "# NumGC = %d\n", s.NumGC)
	fmt.Fprintf(w, "# NumForcedGC = %d\n", s.NumForcedGC)
	fmt.Fprintf(w, "# GCCPUFraction = %v\n", s.GCCPUFraction)
	fmt.Fprintf(w, "# DebugGC = %v\n", s.DebugGC)

  

如果觉得heap profile中打印的活跃对象数和HeapObjects数量差别太大,可以将MemProfileRate设置为一个更小的值(默认为512*1024),设置为1,快照中就可以看到完整的堆对象分配情况。





以上是关于关于Go语言MemoryProfile的一些问题的主要内容,如果未能解决你的问题,请参考以下文章

关于 Go 的一些面试题及答案

关于 Go 的一些面试题及答案

Go -- type 和断言 interface{}转换

关于emoji,Go语言可以这么操作

关于如何理解和运用C语言的指针,我有话说(以C++内的纯C风格解题代讲)

Go语言的匿名函数与闭包的一些理解