GO语言高质量编程--性能分析工具PProf | 青训营笔记

146 阅读2分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第5篇笔记, 第三次课主要讲了GO语言的高质量变成和性能调优实战,本文是针对性能分析工具PProf部分做的笔记

一、功能简介

二、排查实战

1. 搭建pprof实践项目

项目中埋了一些代码炸弹,可以使用pprof排查

2.浏览器查看指标 (http://localhost:6060/debug/pprof/

  • allocs:内存分配情况
  • blocks:阻塞撮作情况
  • cmdline:程序启动命令及
  • goroutine:当前所有goroutine的堆找信息
  • heap:堆上内存使用情况(同alloc)
  • mutex:锁竞争操作情况
  • profile: CPU占用情况
  • threadcreate:当前所有创建的系统线程的堆栈信息
  • trace:程序运行跟踪信息

1. CPU

上述分别是graph,top表格和Source的形式,可以看出占用cpu最多的代码都指向了 tiger.Eat, 检查源代码可以看到确实有问题

func (t *Tiger) Eat() {
	log.Println(t.Name(), "eat")
	loop := 10000000000
	for i := 0; i < loop; i++ {
		// do nothing
	}
}

2. Heap堆内存

  • top表格

  • source

可以看出,占用堆内存最高的代码都指向了mouse.Steal函数, 查看源码如下

const (
	Ki = 1024
	Mi = Ki * Ki
	Gi = Ki * Mi
	Ti = Ki * Gi
	Pi = Ki * Ti
)
func (m *Mouse) Steal() {
	log.Println(m.Name(), "steal")
	max := constant.Gi
	for len(m.buffer) * constant.Mi < max {
		m.buffer = append(m.buffer, [constant.Mi]byte{})
	}
}

3. goroutine协程

  • 火焰图
    • 从上到下表示调用顺序,每一块代表一个函数,越长代表占用cpu时间更长
    • 火焰图是动态的,支持点击块进行分析

  • Source视图

  • 源码
func (w *Wolf) Drink() {
	log.Println(w.Name(), "drink")
	for i := 0; i < 10; i++ {
		go func() {
			time.Sleep(30 * time.Second)
		}()
	}
}

4. mutex锁

  • Source

  • 发现存在一个锁操作,打开source观察, 发现这里sleep了1s才解锁,这个不是业务需要
func (w *Wolf) Howl() {
	log.Println(w.Name(), "howl")

	m := &sync.Mutex{}
	m.Lock()
	go func() {
		time.Sleep(time.Second)
		m.Unlock()
	}()
	m.Lock()
}

5. block阻塞

  • graph

  • source
  • Cat.pee()函数 读取了一个time.After()生成的Channel,这就导致了这个协程阻塞了1s,而不是等待了1s