记一次内存泄露的debug过程
在压测 代码在线运行 工具的时候,发现当并发比较高的时候程序占用的内存会飙升,而且在中断压测之后,内存占用并没有回落。
第一个能想到的办法就是去看代码,但是大多数时候,自己写的代码,很难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
查看代码,发现是 goroutine, ioPipe 的问题,一定是使用姿势出了问题:
于是便有了上面的那段代码,curl http://localhost:6060/go
,查看当前 go routine
的数量;于是猜测是因为 ioPipe 没有正确的关闭,引起 go routine 大量的产生,但是没有退出,耗费大量的内存;于是在异常退出前,主动关闭 ioPipe 的Reader,至此问题解决。
压测验证
本机
wrk -t5 -c20 -d10000s -s post.lua http://tool.lu
服务器
curl http://localhost:6060/go
总结
这是一个很小的bug,由于写代码的时候不仔细,return之前没有关闭资源造成,但却要花费不少的力气去解决;对语言自己提供的工具链需要熟悉在熟悉,这样不管在解决问题或者避免问题的时候,都能节省很多的时间。
建议继续学习:
- 近期Imgsrc一处内存泄露问题的查找和解决 (阅读:5558)
- 了解前端内存泄露 (阅读:4577)
- GLIBC内存分配机制引发的“内存泄露” (阅读:4021)
- GC与JS内存泄露 (阅读:3530)
- 一个 Lua 内存泄露检查工具 (阅读:3095)
- PHP内存耗尽错误分析 (阅读:1871)
- Android应用内存泄露分析、改善经验总结 (阅读:1337)
- Golang socket 里面奇怪的 pipe 使用 (阅读:871)
扫一扫订阅我的微信号:IT技术博客大学习
- 作者:小子 来源: 也就这样,
- 标签: golang proof 内存泄露
- 发布时间:2016-03-16 23:42:05
- [70] Twitter/微博客的学习摘要
- [65] IOS安全–浅谈关于IOS加固的几种方法
- [65] 如何拿下简短的域名
- [64] find命令的一点注意事项
- [63] Go Reflect 性能
- [63] android 开发入门
- [61] 流程管理与用户研究
- [59] 图书馆的世界纪录
- [59] 读书笔记-壹百度:百度十年千倍的29条法则
- [59] Oracle MTS模式下 进程地址与会话信