1. 定位泄漏点

在需要分析的线程中开一个协程监听

go func() {  
   tlog.Infof("pprof http server listening on: %v", 28001)  
   err := http.ListenAndServe(addr, nil)  
   if err != nil {  
      tlog.Fatal("pprof http start failed. err: ", err.Error())  
   }  
}()

需要使用go tool pprof工具分析
命令行输入:go tool pprof http://127.0.0.1:28001/debug/pprof/heap
进入命令行界面输入:top 会显示当前占用内存最高的前几。
或者输入 web 会在浏览器打开内存使用堆栈信息,需要特别注意红色粗线这是内存使用热点方法。

如果没有历史的web界面,或者说从来没看过内存堆栈,那就只能从最大的往下排查,或者直接查一眼就有问题的方法(这个方法占用的内存不应该这么高)。

找到泄露点,如果是异常开辟内存使用,那么改掉就完事。
项目遇到的是引用泄露,方法开辟了内存将引用抛出去,但是那个地方持有引用不知道。导致排查单独很高。(如果有知道如何快速排查的大神请留言)

2. 引用泄露排查小技巧

  1. 第一步不用说分析代码,理一下对象引用可能在那些地方被引用然后逐步分析。
  2. 分析不出来如果上层还是一个对象,在上层对象创建时添加内存开辟的特色代码。目的是为了检测是不是上层泄露,只是泄露点开辟的内存比较多,所以显示在这里。

    // 将下面代码设置在上层对象身上
    testData := make([]int32,10 * 1024 * 1024)
    for i:=0; i < len(testData); i++ {
        testData[i] = 1
    }
  3. 当内存是缓慢上涨并且有会下降,那么可能是达成条件能回收内存。
    在对象生成的地方打印日志,并且加上对象销毁的日志。尝试复现观察什么操作能降低内存,分析操作的代码。

    tlog.Infof("create_object finalized :%v", object.GetID())  
    runtime.SetFinalizer(object, func(o *Object) {  
       tlog.Errorf("object finalized :%v", object.GetID())  
    })
    
    // 强制调用gc的代码,相当于做出相关操作然后调用gc观察是否有回收日志
    runtime.GC()

标签: none

仅有一条评论

  1. 文字流畅如丝,语言优美动人,读来令人心旷神怡。

添加新评论