# golang 에서의 pprof 프로파일링 패키지를 사용해서 코드를 점검할 수 있다.
# 사용하기 위해서는 패키지와 웹리스너용 고루틴 하나 추가하면 된다.
// ysoftman
// pprof 사용 테스트
package main
import (
"fmt"
"log"
"net/http"
_ "net/http/pprof"
"time"
)
func main() {
go func() {
log.Println(http.ListenAndServe("localhost:6060", nil))
}()
for {
time.Sleep(100 * time.Millisecond)
fmt.Println("ysoftman")
}
select {}
}
# pprof.go init()에 이미 다음과 핸들러 들이 등록되 있어 별도로 등록하지 않아도 된다.
func init() {
http.Handle("/debug/pprof/", http.HandlerFunc(Index))
http.Handle("/debug/pprof/cmdline", http.HandlerFunc(Cmdline))
http.Handle("/debug/pprof/profile", http.HandlerFunc(Profile))
http.Handle("/debug/pprof/symbol", http.HandlerFunc(Symbol))
http.Handle("/debug/pprof/trace", http.HandlerFunc(Trace))
}
# 만약 별도 선언 후 /debug/pprof/trace 등 사용시 404 NOT FOUND 가 발생한다면
# 다음과 같이 pprof.Trace 등을 사용하도록 해야 한다.
r.HandleFunc("/pprof/cmdline", pprof.Cmdline)
r.HandleFunc("/pprof/symbol", pprof.Symbol)
r.HandleFunc("/pprof/profile", pprof.Profile)
r.HandleFunc("/pprof/trace", pprof.Trace)
...
# 이제 프로그램을 실행시키고 다음 url 로 접속하면 기본적으로
# block, goroutine, heap, threadcreate 등의 정보를 파악할 수 있다.
http://localhost:6060/debug/pprof/# heap pprof 수행
# pprof 명령은 help 로 파악할 수 있다.
# -http=:9999 를 사용하면 웹(브라우저로 볼 수 있다.)
go tool pprof http://localhost:6060/debug/pprof/heap
Fetching profile over HTTP from http://localhost:6060/debug/pprof/heap
Saved profile in /Users/ysoftman/pprof/pprof.alloc_objects.alloc_space.inuse_objects.inuse_space.009.pb.gz
Type: inuse_space
Time: Apr 9, 2019 at 4:48pm (KST)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top
Showing nodes accounting for 514.63kB, 100% of 514.63kB total
flat flat% sum% cum cum%
514.63kB 100% 100% 514.63kB 100% math/rand.NewSource
0 0% 100% 514.63kB 100% math/rand.init.ializers
0 0% 100% 514.63kB 100% runtime.main
(pprof) exit
# 5초(디폴트30초)간 cpu 프로파일링
go tool pprof http://localhost:6060/debug/pprof/profile?seconds=5
Fetching profile over HTTP from http://localhost:6060/debug/pprof/profile?seconds=5
Please wait... (5s)
Saved profile in /Users/ysoftman/pprof/pprof.samples.cpu.004.pb.gz
Type: cpu
Time: Apr 9, 2019 at 4:55pm (KST)
Duration: 5s, Total samples = 0
No samples were found with the default sample value type.
Try "sample_index" command to analyze different sample values.
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) exit
# 위에서 저장된 프로파일링 파일을 다시 웹으로 볼 수 있다.
go tool pprof -http=:9999 /Users/ysoftman/pprof/pprof.samples.cpu.004.pb.gz
# 또는 go tool 을 이용해 콘솔에서 프로파일링할 수 있다.
# 5초동안 트레이스 덤프
curl 'http://localhost:6060/debug/pprof/trace?seconds=5' -o trace.out
# 트레이스 덤프 보기, http://127.0.0.1:xxxx 로 확인
go tool trace trace.out
# 힙 메모리 덤프
curl 'http://localhost:6060/debug/pprof/heap' -o heap.out
# 힙 메모리중 가장 많이 사용하 부분 보기
go tool pprof heap.out
(pprof) top
# golang 1.11 pprof 부터 flamegrpah 로 볼 수 있다.
go tool pprof -http=:8080 heap.out 으로 웹페이지 띄우고 view -> flame graph
#####
# gin web framework 사용시는 다음과 같이 사용한다.
# timeoutmiddleware 등이 설정되어 있다면 /debug/pprof 경로는 타임아웃대상에서 예외 처리하자.
import "github.com/gin-contrib/pprof"
func main() {
router := gin.Default()
pprof.Register(router, "/debug/pprof")
// 또는 pprof 접근을 admin 으로 제한하고 싶을때
adminGroup := router.Group("/admin", func(c *gin.Context) {
if c.Request.Header.Get("Authorization") != "foobar" {
c.AbortWithStatus(http.StatusForbidden)
return
}
c.Next()
})
pprof.RouteRegister(adminGroup, "pprof")
router.Run(":8080")
}
# 프로파일링 및 결과 보기
curl 'http://localhost:8080/debug/pprof/heap?seconds=10' -o heap.out
go tool pprof -http=:9090 heap.out
curl 'http://localhost:8080/debug/pprof/profile?seconds=10' -o profile.out
go tool pprof -http=:9090 profile.out