IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

记一次内存泄露的debug过程

也就这样, 2016-03-16 23:42:05 累计浏览 2,404 次
本机暂存

   在压测 代码在线运行 工具的时候,发现当并发比较高的时候程序占用的内存会飙升,而且在中断压测之后,内存占用并没有回落。

   第一个能想到的办法就是去看代码,但是大多数时候,自己写的代码,很难review出太多的问题;于是就借助golang的pprof来定位问题。

在程序中嵌入 pprof

package main

import (

   "tool.lu/sandbox-server/app"

   "net/http"

   _ "net/http/pprof"

   "strconv"

   "runtime"

)

func main() {

   debug()

   server := app.NewApp()

   server.Run(":9090")

}

func debug() {

   go func() {

       // 这边是由于通过pprof发现问题之后,加的一段debug代码;后面会讲到

       http.HandleFunc("/go", func(w http.ResponseWriter, r *http.Request) {

           num := strconv.FormatInt(int64(runtime.NumGoroutine()), 10)

           w.Write([]byte(num))

       })

       http.ListenAndServe("localhost:6060", nil)

   }()

}

   通过 go tool 工具,查看内存分配最多的 top 5

go tool pprof http://localhost:6060/debug/pprof/heap

top 5

   Screenshot 2016-02-07 at 17.55.39.png

   查看代码,发现是 goroutine, ioPipe 的问题,一定是使用姿势出了问题:

   Screenshot 2016-02-07 at 17.56.40.png

   于是便有了上面的那段代码,curl http://localhost:6060/go,查看当前 go routine 的数量;于是猜测是因为 ioPipe 没有正确的关闭,引起 go routine 大量的产生,但是没有退出,耗费大量的内存;于是在异常退出前,主动关闭 ioPipe 的Reader,至此问题解决。

压测验证

   本机

wrk -t5 -c20 -d10000s -s post.lua http://tool.lu

   服务器

   Screenshot 2016-02-07 at 16.24.24.png

curl http://localhost:6060/go

总结

   这是一个很小的bug,由于写代码的时候不仔细,return之前没有关闭资源造成,但却要花费不少的力气去解决;对语言自己提供的工具链需要熟悉在熟悉,这样不管在解决问题或者避免问题的时候,都能节省很多的时间。

同分类推荐文章

  1. 等了十年的 Go 链式管道,终于来了:seq 让你像写 Scala 一样写 Go (2026-06-25 18:38:18)
  2. Go 实验特性详解 (2026-06-21 10:05:27)
  3. amd64 微架构级别对 Go 程序性能提升多少? (2026-06-21 09:38:49)

查看更多 后端 文章 →

建议继续学习

  1. Linux 性能监控、测试、优化工具 (累计阅读 13,010)
  2. 长连接(KeepAlive)在 http 连接中的性能影响 (累计阅读 8,780)
  3. redis在大数据量下的压测表现 (累计阅读 8,292)
  4. 并发编程系列之一:锁的意义 (累计阅读 7,569)
  5. HBase随机写以及随机读性能测试 (累计阅读 7,546)
  6. 无锁HashMap的原理与实现 (累计阅读 6,743)
  7. 基于 PhoneGap 与 Java 开发的 Android 应用的性能对比 (累计阅读 6,406)
  8. Nginx源码分析-事件循环 (累计阅读 6,256)
  9. Unix高级环境编程系列笔记 (累计阅读 5,977)
  10. Nginx 还是 Varnish? (累计阅读 5,331)