成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Go1.23 新特性:花了近 10 年,time.After 終于不泄漏了!

開發 前端
今天給大家分享了一個花了將近 10 年,Go 才解決的計時器泄露問題。為此還是要給 rsc 點贊的,至少一直都有記著。就是這個解決速度比較慢,很多人在真實的 Go 工程中都已經遇到過了。

大家好,我是煎魚。

好多年前,我寫過 timer.After 的使用和坑。Go 這么多年以來這塊一直有內存泄露。有的同學或多或少都有遇到過。

最近 Go1.23 即將正式發布,Go 核心團隊負責人 rsc 自述花了將近 10 年的努力,終于把這個問題修復了。值得我們關注!

timer.After 是什么

這是之前編寫的部分,我測試驗證了下。在 Go1.22 依然有效,仍然是有問題的。因此沒有做什么修改。主要是給大家做知識溫習回顧的作用。

今天是男主角是 Go 標準庫 time 所提供的 After 方法。函數簽名如下:

func After(d Duration) <-chan Time

該方法可以在一定時間(根據所傳入的 Duration)后主動返回 time.Time 類型的 channel 消息。

在常見的場景下,我們會基于此方法做一些計時器相關的功能開發,例子如下:

func main() {
    ch := make(chan string)
    go func() {
        time.Sleep(time.Second * 3)
        ch <- "腦子進煎魚了"
    }()

    select {
    case _ = <-ch:
    case <-time.After(time.Second * 1):
        fmt.Println("煎魚出去了,超時了!!!")
    }
}

在運行 1 秒鐘后,輸出結果:

煎魚出去了,超時了!!!

上述程序在在運行 1 秒鐘后將觸發 time.After 方法的定時消息返回,輸出了超時的結果。

有什么問題和坑

從例子來看似乎非常正常,也沒什么 “坑” 的樣子。莫非是虛晃一槍?

我們再看一個不像是有問題例子,這在 Go 工程中經常能看見,只是大家都沒怎么關注。

代碼如下:

func main() {
    ch := make(chan int, 10)
    go func() {
        in := 1
        for {
            in++
            ch <- in
        }
    }()

    for {
        select {
        case _ = <-ch:
            // 煎魚干了點什么...
            continue
        case <-time.After(3 * time.Minute):
            fmt.Printf("現在是:%d,我腦子進煎魚了!", time.Now().Unix())
        }
    }
}

在上述代碼中,我們構造了一個 for+select+channel 的一個經典的處理模式。

同時在 select+case 中調用了 time.After 方法做超時控制,避免在 channel 等待時阻塞過久,引發其他問題。

看上去都沒什么問題,但是細心一看。在運行了一段時間后,我的筆記本電腦已經溫熱了許多。

粗暴的利用 top 命令一看:

圖片圖片

例子中 Go 工程的內存占用竟然已經達到了 30+GB 之高,并且還在持續增長。在再等待了一段時間后(所設置的超時時間到達),Go 工程的內存占用也沒有要恢復合理的數值。這非常可怕。

這明顯就是存在內存泄露的問題。

問題原因

這個內存泄露的問題,無容置疑是 Go 官方認可的 BUG。

快速的用一句話來講,核心原因在于:for select 已結束,無法被 GC,時間堆內的被觸發的計時器還在。

Go 官方文檔說明Go 官方文檔說明

如果是想深入看原因可以查看以前我寫的《Go 內存泄露之痛,這篇把 Go timer.After 問題根因講透了!》

Go1.23 timer.After 不泄露了!

在現在 2024 年,經過將近十年的努力,Go 核心團隊負責人 rsc 終于解決了這個問題!!!

圖片圖片

自 Go1.23 版本起,會對用于計時器的通道(或者可能是用于通道的計時器)進行特殊處理,以便當沒有通道操作待處理時,計時器將不會存放在計時器堆中。

這意味著當一旦不再引用通道和計時器,就可以對其進行 GC,不必等待計時器到期或明確停止計時器。

注:這里的計時器是指 time.After、time.NewTimer 和 time.NewTicker 使用的數據結構。

測試和驗證

可能會有的同學會想體驗 Go1.23 的新特性,驗證這個 time.After 的修復是否有效。要特別注意下面這一點。

我們還是用前面提到的問題代碼來測試。但如果你直接在本地復用,可能不一定能生效,會看到還是有內存泄露的情況。

主要是兩個原因,如下:

1、你要下載 Go 新版本并使用 Go1.23 運行:

// 安裝 go1.23rc2 的 go 新版本
$ go install golang.org/dl/go1.23rc2@latest
$ go1.23rc2 download

// 運行煎魚前面的代碼例子
$ go1.23rc2 run main.go

2、項目的 go.mod 文件注意 go 版本在 1.23,否則該新特性將由于兼容性保障無法生效:

圖片圖片

運行一段時間后,之前的代碼中 Go1.23rc2 下內存情況基本正常:

圖片圖片

總結

今天給大家分享了一個花了將近 10 年,Go 才解決的計時器泄露問題。為此還是要給 rsc 點贊的,至少一直都有記著。就是這個解決速度比較慢,很多人在真實的 Go 工程中都已經遇到過了。

另外從新版本開始,大家在舊項目體驗新特性是,要注意項目 go.mod 的 go 行版本或是 go toolchain 版本,避免由于版本過低而無法測試到真實的新特性效果。

責任編輯:武曉燕 來源: 腦子進煎魚了
相關推薦

2024-08-07 08:51:20

Go優化開發

2024-09-09 08:56:03

2024-08-20 08:51:41

2025-03-03 00:05:00

GoTimer調度器

2024-09-02 00:30:41

Go語言場景

2020-09-22 07:49:05

內存泄漏

2021-08-30 10:49:39

Go語言編譯器

2018-10-31 12:41:11

2021-12-09 08:50:35

Kubernetes增強功能版本更新

2021-09-05 18:25:30

Go命令倉庫

2017-12-18 17:21:56

AndroidJava內存泄漏

2024-01-22 00:30:00

Go編程Go 1.22

2010-07-20 10:19:06

Wine 1.2

2019-03-05 15:03:09

Android Q安卓系統功能

2024-09-02 10:21:21

2025-05-06 05:00:00

2020-10-10 09:01:54

泄漏

2025-01-21 15:10:36

2022-02-11 21:01:18

GoNetip網絡庫

2024-04-28 09:01:06

React 19更新前端
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产视频久久久久 | 欧美一区二区三区视频在线 | 久久毛片| www中文字幕 | 在线看av网址 | 国产日韩欧美一区 | 日韩福利| 国产一区久久久 | 日韩在线观看中文字幕 | 国产婷婷色综合av蜜臀av | 国产高清在线 | 久久精品一区二 | 国产精品久久久久久久久免费樱桃 | 欧美二区在线 | 在线精品一区二区三区 | 国产成人精品一区二区三区在线 | 影音先锋中文字幕在线观看 | 蜜臀网| 欧美精品久久久 | 国产成人精品久久二区二区91 | 亚洲欧美日韩精品久久亚洲区 | 欧美一区视频 | 国产精品免费大片 | 亚洲精品91 | 国产高清在线视频 | 精品国产精品一区二区夜夜嗨 | 中文字幕1区2区 | 久草视频2 | 免费在线观看一级毛片 | 91九色视频在线 | 影音先锋中文字幕在线观看 | www,黄色,com| 伊人免费在线观看 | 国产偷录视频叫床高潮对白 | 亚洲午夜视频在线观看 | 久久成人精品 | 日韩电影免费在线观看中文字幕 | 视频在线一区二区 | 一级做a爰片性色毛片16美国 | 精品久久久久久久久久 | 精品亚洲一区二区三区四区五区 |