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),因此不能使用寫屏障,所以很難確定一個協程是否可以當成垃圾回收。