🎃
[Go1.26]Goroutine leak profileを試してみた
Goroutine leak profileとは
Go1.26で実験的に導入される機能
runtime/pprofにgoroutineleakと言うプロファイル形式が入りました。
buildや実行のタイミングでGOEXPERIMENT=goroutineleakprofileとすると有効化できる。
また有効化することで、net/http/pprofからも参照できるようになるとのこと。
まずはリークするコードを書いてみましょう
package main
import (
"log"
"net/http"
_ "net/http/pprof"
)
func leakWorker(ch chan int) {
ch <- 1
}
func main() {
ch := make(chan int)
go leakWorker(ch)
log.Println("pprof listen on :6060")
log.Fatal(http.ListenAndServe("localhost:6060", nil))
}
このコードはch <- 1が受信がないことでleakが起きる実装です。
build後、go toolを実行し状況を確認
▶ go tool pprof http://localhost:6060/debug/pprof/goroutineleak
Fetching profile over HTTP from http://localhost:6060/debug/pprof/goroutineleak
Saved profile in /pprof/pprof.leak-test.goroutineleak.006.pb.gz
File: leak-test
Type: goroutineleak
Time: 2026-01-03 18:21:45 JST
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top
Showing nodes accounting for 1, 100% of 1 total
flat flat% sum% cum cum%
1 100% 100% 1 100% runtime.gopark
0 0% 100% 1 100% main.leakWorker
0 0% 100% 1 100% runtime.chansend
0 0% 100% 1 100% runtime.chansend1
(pprof) list leakWorker
Total: 1
ROUTINE ======================== main.leakWorker in ~/sandbox/sample-goroutine-leak/main.go
0 1 (flat, cum) 100% of Total
. . 9:func leakWorker(ch chan int) {
. 1 10: ch <- 1
. . 11:}
. . 12:
. . 13:func main() {
. . 14: ch := make(chan int)
. . 15: go leakWorker(ch)
(pprof)
今の状態だとリークしていることがわかります。
list leakWorkerでより詳細にリークしているがつかめます。
ではleak、リークを修正しましょう。
func main() {
---
<-ch // 受け取れるように追加
}
今は受信先がいないので起きているので、<-chと追加するだけでリークが解消されると思います。
▶ go tool pprof http://localhost:6060/debug/pprof/goroutineleak
Fetching profile over HTTP from http://localhost:6060/debug/pprof/goroutineleak
Saved profile in /pprof/pprof.leak-test.goroutineleak.005.pb.gz
File: leak-test
Type: goroutineleak
Time: 2026-01-04 10:25:04 JST
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top
Showing nodes accounting for 0, 0% of 0 total
flat flat% sum% cum cum%
確認するとリークが解消されました。
Discussion