go runtime.malg导致的内存泄漏
最近在压测我们的服务,发现流量超过服务承受的极限后,出现协程暴涨,内存暴涨,延时大大增加的现象,但是把压测流量停止之后,携程数量会恢复正常,内存却恢复不了,利用pprof采集了一下,如下图所示:
去搜寻了大量资料之后,发现go的官网早就有这个issue(官方issue),大佬们知道,只是不好解决,描述如下:
Your observation is correct. Currently the runtime never frees the g objects created for goroutines, though it does reuse them. The main reason for this is that the scheduler often manipulates g pointers without write barriers (a lot of scheduler code runs without a P, and hence cannot have write barriers), and this makes it very hard to determine when a g can be garbage collected.
大致原因就是go的gc采用的是并发垃圾回收,调度器在操作协程指针的时候不使用写屏障(可以看看draveness大佬的分析),因为调度器在很多执行的时候需要使用P(GPM),因此不能使用写屏障,所以很难确定一个协程是否可以当成垃圾回收。