赞
踩
内存溢出(out of memory,简称OOM)
内存溢出是指程序在申请内存时,没有足够的内存空间供其使用,简单点说就是你要求分配的内存超出了系统能给你的,系统不能满足需求,于是产生溢出出现out of memory异常。
内存泄露(memory leak)
内存泄露是指程序在申请内存后,无法释放已申请的内存空间,简单点说就是你向系统申请分配内存进行使用(new),可是使用完了以后却不归还(delete),结果你申请到的那块内存你自己也不能再访问(也许你把它的地址给弄丢了),而系统也不能再次将它分配给需要的程序。
内存泄露指的是程序运行过程中已不再使用的内存,没有被释放掉,导致这些内存无法被使用,直到程序结束这些内存才被释放的问题。
Go虽然有GC来回收不再使用的堆内存,减轻了开发人员对内存的管理负担,但这并不意味着Go程序不再有内存泄露问题。
分配的内存不足以放下数据项序列,称为内存溢出。
对于 C 和 C++ 这种没有 Garbage Collection 的语言来讲,我们主要关注两种类型的内存泄漏:
1、堆内存泄漏(Heap leak)
堆内存指的是程序运行中根据需要分配通过 malloc,realloc new 等从堆中分配的一块内存,再是完成后必须通过调用对应的 free 或者 delete 删掉。如果程序的设计的错误导致这部分内存没有被释放,那么此后这块内存将不会被使用,就会产生 Heap Leak。
2、系统资源泄露(Resource Leak)
主要指程序使用系统分配的资源比如 Bitmap,handle ,SOCKET 等没有使用相应的函数释放掉,导致系统资源的浪费,严重可导致系统效能降低,系统运行不稳定。
不是所有的out of memory都是memory leak导致的,但是memory leak会最终会导致out of memory!
关于Go的内存泄露:10次内存泄露,有9次是goroutine泄露。
所以:掌握了如何定位和解决goroutine泄露,就掌握了Go内存泄露的大部分场景。
pprof是Go的性能分析工具,在程序运行过程中,可以记录程序的运行信息,可以是CPU使用情况、内存使用情况、goroutine运行情况等,当需要性能调优或者定位Bug时候,这些记录的信息是相当重要。
使用pprof有多种方式,Go已经现成封装好了1个:net/http/pprof
,使用简单的几行命令,就可以开启pprof,记录运行信息,并且提供了Web服务,能够通过浏览器和命令行2种方式获取运行数据。
看个demo:
- package main
-
- import (
- "fmt"
- "net/http"
- _ "net/http/pprof"
- )
-
- func main() {
- // 开启pprof,监听请求
- ip := "0.0.0.0:6060"
- if err := http.ListenAndServe(ip, nil); err != nil {
- fmt.Printf("start pprof failed on %s\n", ip)
- }
输入网址ip:port/debug/pprof/
打开pprof主页,从上到下依次是5类profile信息:
full goroutine stack dump
是输出所有goroutine的调用栈,是goroutine的debug=2,后面会详细介绍。
使用命令go tool pprof url
可以获取指定的profile文件,此命令会发起http请求,然后下载数据到本地之后进入交互式模式,就像gdb一样,可以使用命令查看运行信息,以下是5类请求的方式:
- # 下载cpu profile,默认从当前开始收集30s的cpu使用情况,需要等待30s
- go tool pprof http://localhost:6060/debug/pprof/profile # 30-second CPU profile
- go tool pprof http://localhost:6060/debug/pprof/profile?seconds=120 # wait 120s
-
- # 下载heap profile
- go tool pprof http://localhost:6060/debug/pprof/heap # heap profile
-
- # 下载goroutine profile
- go tool pprof http://localhost:6060/debug/pprof/goroutine # goroutine profile
-
- # 下载block profile
- go tool pprof http://localhost:6060/debug/pprof/block # goroutine blocking profile
-
- # 下载mutex profile
- go tool pprof http://localhost:6060/debug/pprof/mutex
请求之后会展示以下信息:
/home/ubuntu/pprof/pprof.demo.alloc_objects.alloc_space.inuse_objects.inuse_space.001.pb.gz
,这其中包含了程序名demo
,profile类型alloc
已分配的内存,inuse
代表使用中的内存。help
可以获取帮助,最先会列出支持的命令,想掌握pprof,要多看看,多尝试。关于命令,本文只会用到3个,我认为也是最常用的:top
、list
、traces
,分别介绍一下。top会列出5个统计数据:
怎么发现内存泄露
goroutine泄露的本质是channel阻塞,无法继续向下执行,导致此goroutine关联的内存都无法释放,进一步造成内存泄露。
利用好go pprof获取goroutine profile文件,然后利用3个命令top、traces、list定位内存泄露的原因。
泄露的场景不仅限于以下两类,但因channel相关的泄露是最多的。
channel的读或者写:
为避免goroutine泄露造成内存泄露,启动goroutine前要思考清楚:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。