Go에서 pprof를 사용하여 메모리 유출을 확인하는 방법
개시하다
업무 개발 시스템에서 메모리 유출이 발생했기 때문에 pprof에서 유출 위치를 확인하는 방법을 조사했다.
이 기사에도 자신의 필기가 포함되어 있다.
다른 더 좋은 방법과 오류가 있을지도 모르니 참고하세요.
결론
pprof
중-diff_base
을 사용하면 두 분석 결과의 차이에 따라 메모리 유출 위치를 확정할 수 있다.확인
실제 사용된 메모리 유출의 샘플 코드는 다음과 같다.(함수 이름 등)
!
고로틴 유출 검증도 겸하고
ctx.Done()
시 리턴을 하지 않아 고로틴이 유출됐다.샘플 코드
package main
import (
"context"
"log"
"net/http"
_ "net/http/pprof"
"time"
)
var m []byte
func watchFile(ctx context.Context) {
for i := 0; i < 1048576; i++ {
m = append(m, 65)
}
log.Println("start watching file")
defer log.Println("end watching file")
ticker := time.NewTicker(1 * time.Second)
for {
select {
case time := <-ticker.C:
println("check file's timestamp", time.Local().Format("2006/01/02 15:04:05"))
case <-ctx.Done():
ticker.Stop()
}
}
}
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithCancel(context.Background())
go watchFile(ctx)
time.AfterFunc(3*time.Second, func() {
cancel()
})
})
log.Println("start http server :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
검증 결과
다음 명령을 두 번 실행합니다.
두 번째 실행은 첫 번째 로그 출력이 멈춘 후에 진행됩니다.
for i in {1..10};do curl localhost:8080; done
명령을 처음 실행할 때의 메모리 사용량은 9489.30kB
이다.skanehira@godzilla github.com/skanehira/go-memory-leak-example $ go tool pprof /Users/skanehira/pprof/pprof.alloc_objects.alloc_space.inuse_objects.inuse_space.016.pb.gz
toType: inuse_space
Time: Mar 28, 2022 at 11:44pm (JST)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top
Showing nodes accounting for 12564.15kB, 100% of 12564.15kB total
Showing top 10 nodes out of 19
flat flat% sum% cum cum%
9489.30kB 75.53% 75.53% 9489.30kB 75.53% main.watchFile
2562.81kB 20.40% 95.92% 2562.81kB 20.40% runtime.allocm
512.04kB 4.08% 100% 512.04kB 4.08% runtime.bgscavenge
0 0% 100% 512.56kB 4.08% runtime.gopreempt_m
0 0% 100% 512.56kB 4.08% runtime.goschedImpl
0 0% 100% 512.56kB 4.08% runtime.handoffp
0 0% 100% 1025.12kB 8.16% runtime.mcall
0 0% 100% 512.56kB 4.08% runtime.morestack
0 0% 100% 1025.12kB 8.16% runtime.mstart
0 0% 100% 1025.12kB 8.16% runtime.mstart0
두 번째 명령을 실행할 때의 메모리 사용량은 23208kB
이다.skanehira@godzilla github.com/skanehira/go-memory-leak-example $ go tool pprof /Users/skanehira/pprof/pprof.alloc_objects.alloc_space.inuse_objects.inuse_space.017.pb.gz
Type: inuse_space
Time: Mar 28, 2022 at 11:44pm (JST)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top
Showing nodes accounting for 27819.46kB, 100% of 27819.46kB total
Showing top 10 nodes out of 25
flat flat% sum% cum cum%
23208kB 83.42% 83.42% 23208kB 83.42% main.watchFile
2562.81kB 9.21% 92.64% 2562.81kB 9.21% runtime.allocm
1536.61kB 5.52% 98.16% 1536.61kB 5.52% time.goFunc
512.04kB 1.84% 100% 512.04kB 1.84% runtime.bgscavenge
0 0% 100% 1536.61kB 5.52% runtime.checkTimers
0 0% 100% 1536.61kB 5.52% runtime.findrunnable
0 0% 100% 512.56kB 1.84% runtime.gopreempt_m
0 0% 100% 512.56kB 1.84% runtime.goschedImpl
0 0% 100% 512.56kB 1.84% runtime.handoffp
0 0% 100% 2561.73kB 9.21% runtime.mcall
(pprof)
-diff_base
를 사용하여 차분을 확인한 후 첫 번째와 두 번째 차이13.40MB
23208kB(2回目)
-9489.30kB(1回目)
=13718.7kB(13.397168MB)
이기 때문에flat값과 일치합니다.즉
-diff_base
를 사용하여 두 결과를 비교했을 때flat
의 메모리 사용량이 사실상 증가한 것이다.skanehira@godzilla github.com/skanehira/go-memory-leak-example $ go tool pprof -diff_base /Users/skanehira/pprof/pprof.alloc_objects.alloc_space.inuse_objects.inuse_space.016.pb.gz /Users/skanehira/pprof/pprof.alloc_objects.alloc_space.inuse_objects.inuse_space.017.pb.gz
Type: inuse_space
Time: Mar 28, 2022 at 11:44pm (JST)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top
Showing nodes accounting for 14.90MB, 121.42% of 12.27MB total
flat flat% sum% cum cum%
13.40MB 109.19% 109.19% 13.40MB 109.19% main.watchFile
1.50MB 12.23% 121.42% 1.50MB 12.23% time.goFunc
0 0% 121.42% 1.50MB 12.23% runtime.checkTimers
0 0% 121.42% 1.50MB 12.23% runtime.findrunnable
0 0% 121.42% 1.50MB 12.23% runtime.mcall
0 0% 121.42% 1.50MB 12.23% runtime.park_m
0 0% 121.42% 1.50MB 12.23% runtime.runOneTimer
0 0% 121.42% 1.50MB 12.23% runtime.runtimer
0 0% 121.42% 1.50MB 12.23% runtime.schedule
0 0% 121.42% 1.50MB 12.23% runtime.stealWork
(pprof)
최후
-diff_base
는 메모리뿐만 아니라 두 개profile
를 비교하는 옵션이기 때문에 goroutine
의 유출 등도 확인할 수 있다.편하네.
Reference
이 문제에 관하여(Go에서 pprof를 사용하여 메모리 유출을 확인하는 방법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/skanehira/articles/2022-03-29-go-investigation-memory-leak텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)