GOLANG中time.After釋放的問題
在謝大群裡看到有同學在討論time.After
洩漏的問題,就算時間到了也不會釋放,瞬間就驚呆了,忍不住做了試驗,結果發現應該沒有這麼的恐怖的,是有洩漏的風險不過不算是洩漏,先看API的說明:
// After waits for the duration to elapse and then sends the current time
// on the returned channel.
// It is equivalent to NewTimer(d).C.
// The underlying Timer is not recovered by the garbage collector
// until the timer fires. If efficiency is a concern, use NewTimer
// instead and call Timer.Stop if the timer is no longer needed.
func After(d Duration) <-chan Time {
return NewTimer(d).C
}
提到了一句The underlying Timer is not recovered by the garbage collector
,這句挺嚇人不會被GC回收,不過後面還有條件until the timer fires
,說明fire
後是會被回收的,所謂fire
就是到時間了,寫個例子證明下壓壓驚:
package main
import "time"
func main() {
for {
<- time.After(10 * time.Nanosecond)
}
}
顯示記憶體穩定在5.3MB,CPU為161%,肯定被GC回收了的。當然如果放在goroutine也是沒有問題的,一樣會回收:
package main
import "time"
func main() {
for i := 0; i < 100; i++ {
go func(){
for {
<- time.After(10 * time.Nanosecond)
}
}()
}
time.Sleep(1 * time.Hour)
}
只是資源消耗會多一點,CPU為422%,記憶體佔用6.4MB。因此:
Remark: time.After(d)在d時間之後就會
fire
,然後被GC回收,不會造成資源洩漏的。
那麼API所說的If efficieny is a concern, user NewTimer instead and call Timer.Stop
是什麼意思呢?這是因為一般time.After
會在select中使用,如果另外的分支跑得更快,那麼timer是不會立馬釋放的(到期後才會釋放),比如這種:
select {
case time.After(3*time.Second):
return errTimeout
case packet := packetChannel:
// process packet.
}
如果packet非常多,那麼總是會走到下面的分支,上面的timer不會立刻釋放而是在3秒後才能釋放,和下面程式碼一樣:
package main
import "time"
func main() {
for {
select {
case <-time.After(3 * time.Second):
default:
}
}
}
這個時候,就相當於會堆積了3秒的timer沒有釋放而已,會不斷的新建和釋放timer,記憶體會穩定在2.8GB,這個當然就不是最好的了,可以主動釋放:
package main
import "time"
func main() {
for {
t := time.NewTimer(3*time.Second)
select {
case <- t.C:
default:
t.Stop()
}
}
}
這樣就不會佔用2.8GB記憶體了,只有5MB左右。因此,總結下這個After的說明:
- GC肯定會回收
time.After
的,就在d之後就回收。一般情況下讓系統自己回收就好了。 - 如果有效率問題,應該使用
Timer
在不需要時主動Stop。大部分時候都不用考慮這個問題的。
交作業。
相關文章
- golang中的鎖競爭問題Golang
- golang 釋放記憶體機制的探索Golang記憶體
- vector clear() 方法 記憶體釋放問題記憶體
- Go坑:time.After可能導致的記憶體洩露問題分析Go記憶體洩露
- Hue的Impala模組沒有釋放連線的問題解決
- 開放世界遊戲中的原路返回問題或直接傳送問題分析遊戲
- golang關鍵字select的三個例子, time.After模擬socket/心跳超時Golang
- 處理Linux刪除檔案後空間未釋放的問題Linux
- (轉載)刪除檔案後硬碟空間不釋放的問題硬碟
- iOS 解決設定rootViewController 記憶體不釋放問題iOSViewController記憶體
- Linux檔案刪除但空間不釋放問題篇Linux
- golang json處理問題GolangJSON
- Golang GRPC 環境 問題GolangRPC
- golang中http server.go中的testHookServerServe函式變數寫法問題GolangHTTPServerHook函式變數
- DevExpress 的LayoutControl控制元件導致資源無法釋放的問題處理devExpress控制元件
- 深入解析 TiFlash丨多併發下執行緒建立、釋放的阻塞問題執行緒
- golang 面試常考問題Golang面試
- golang slice使用不慎導致的問題Golang
- golang開發:http請求redirect的問題GolangHTTP
- 解決golang 的記憶體碎片問題Golang記憶體
- 記一次 Redisson 線上問題 → 你怎麼能釋放別人的鎖Redis
- 解決刪除檔案後 WSL2 磁碟空間不釋放的問題
- golang遍歷channel時return問題Golang
- 新手入門 Golang 常見問題Golang
- html檔案中的php程式碼被註釋掉的問題HTMLPHP
- 如何在 pyqt 中解決啟用 DPI 縮放後 QIcon 模糊的問題QT
- golang 解析php輸出json相容問題GolangPHPJSON
- Redis中的問題Redis
- 用筆記來記錄遇到的問題:釋出版本和非釋出版本遇到的問題筆記
- Blazor釋出到IIS中頁面一片空白的問題Blazor
- 開放世界遊戲仍然存在的10個問題遊戲
- 兩個考研政治很多人問題但是解釋通的問題
- FreshTomato 2021.5釋出,終於解決了萬能中繼的問題中繼
- Chrome 再次最佳化記憶體佔用問題,新增記憶體釋放開關Chrome記憶體
- js中this的指向問題JS
- hibernate中的no session問題Session
- vector 的記憶體釋放記憶體
- linux 釋放埠Linux
- linux埠釋放Linux