go tool pprof
프로그램:- pprof 데이터를 분석하여 보여 주는 pprof 바이너리다.
runtime/pprof
패키지:- Go 프로그램으로부터 pprof 데이터를 생성하여 내보내는 일을 하는 패키지다.
net/http/pprof
패키지:runtime/pprof
패키지가 하고 있는 것을 (ServeHTTP로) 웹으로 내보내거나 프로그램의 pprof 데이터를 분석하여 웹 인터페이스로 보여 주는 일을 하는 패키지다.
runtime/pprof
또는 net/http/pprof
를 이용하여 생성한 pprof 데이터
를 go tool pprof
에 제공하면 go tool pprof
가 가공하여 출력한다.
데이터를 그래프로 시각화하여 pdf로 내보내는 명령어 예제:
go tool pprof -pdf your_raw_pprof_data_name > out.pdf
30초 간의 CPU 프로파일을 받아보기:
go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30
go tool pprof
와 비슷한 것으로 go tool trace
라는 툴도 있다:
go tool trace http://localhost:6060/debug/pprof/trace?seconds=5
자세한 것은 go tool pprof -h
에서 찾는다.
-
프로그램에 현존하는 모든 프로파일을 받아오는 함수
func runtime.pprof.Profiles() []*Profile
-
프로그램에 현존하는 프로파일 하나를 이름으로 지정하여 받아오는 함수
func runtime.pprof.Lookup(name string) *Profile
-
프로파일 객체
func (p *Profile) Count() int
// 항목의 실행 스택 수. 가령 "goroutine"의 프로파일이라면 고루틴의 수가 됨.func (p *Profile) Name() string
// 작성 시점 기준으로 "allocs", "block", "goroutine", "heap", "mutex", "threadcreate" 가운데 하나.func (p *Profile) WriteTo(w io.Writer, debug int) error
// 프로파일의 내용을 써서 내보냄. 두 번째 인자로 넘기는 것은 '디버그 수준'이라고 하는데 아래에 이어서 적음.
프로파일의 '디버그 수준'은 내보내는 데이터의 형식을 지정함. (자작 변수명
nDebugLevel
)0
이면 gz로 압축된 프로토버프 형식. (이 형식이어야 실행 프로그램의 원본 바이너리 제공 없이go tool pprof
로 바로 분석할 수 있다.)1
이면 프로그래머가 편하게 읽어볼 수 있는 비교적 간결한 텍스트 형식. (몇 번째 코드에서 몇 번이나 일어났다는 점을 중복 없이 짧게 적음.)2
이면 런타임 패닉 로그 수준으로 스택 트레이스가 자세히 기술된 텍스트 형식이다. (0이나 1의 그것에 비해 별로 쓸모 없음.)0
,1
,2
이외의 수는 작성 시점을 기준으로 무효하며 무의미함.
-
헷갈리게 하는 쓸모 없는 함수
func runtime.pprof.WriteHeapProfile(w io.Writer) error
- 하위 호환성을 위해 유지되고 있는
pprof.WriteHeapProfile
이라는 쓸모 없는 함수가 있다. pprof.WriteHeapProfile(w)
의 호출은pprof.Lookup("heap").WriteTo(w, 0)
와 동일하다.- 힙 프로파일은 메모리 프로파일이라고도 하는데 특별하게 다뤄지는 모양이다.
- 하위 호환성을 위해 유지되고 있는
-
측정 함수
위에서 언급한 프로파일들처럼 프로그램의 한 순간의 상태를 담은 데이터가 아닌 일정 기간 동안 이어진 행위에 대한 프로파일링을 별도로 한다.
func runtime.pprof.StartCPUProfile(w io.Writer) error func runtime.pprof.StopCPUProfile()
net/http/pprof
는 모든 pprof 데이터를 시각화하여 웹 브라우저 상에서 확인할 수 있게 한다.
func init() {
http.HandleFunc("/debug/pprof/", Index)
http.HandleFunc("/debug/pprof/cmdline", Cmdline)
http.HandleFunc("/debug/pprof/profile", Profile)
http.HandleFunc("/debug/pprof/symbol", Symbol)
http.HandleFunc("/debug/pprof/trace", Trace)
}
아래처럼 임포트하면 DefaultServeMux
에 net.http.pprof.init()
함수가 핸들러를 등록한다.
import _ "net/http/pprof"
그리고 다음과 같이 웹서버를 실행한다.
http.ListenAndServe("localhost:8080", nil) // nil 또는 http.DefaultServeMux
그러면 아래 주소에서 프로파일링 데이터를 확인할 수 있다.
http://localhost:8080/debug/pprof/
다음과 같은 프로파일 객체를 시각화하거나 압축된 프로토버프 형식으로 제공한다.
- "allocs", "block", "goroutine", "heap", "mutex", "threadcreate"
- "profile": 주어진 몇 초 동안의 CPU 프로파일
- "trace": 주어진 몇 초 동안의 전체 스택 트레이스 (
go tool pprof
가 아닌go tool trace
로 분석하는 full stack trace) - "cmdline": 명령줄 프로그램 인스턴스 나열 (필자는 인스턴스가 하나 있는 것밖에 못 봄)
- "symbol": 심볼인 듯함
net.http.pprof
패키지 자체는 핸들러 함수를 등록하고 그것을 내보낼 뿐이다. 아래 나열된 것이 패키지의 모든 수출(export) 함수다.
func Handler(name string) http.Handler
// "allocs", "block", "goroutine", "heap", "mutex", "threadcreate" 등 이름을 지정해서 해당 핸들러를 받아올 수 있음func Index(w http.ResponseWriter, r *http.Request)
// "allocs", "block", "goroutine", "heap", "mutex", "threadcreate" 로 넘어가기 직전의 인덱스 페이지func Profile(w http.ResponseWriter, r *http.Request)
// 30초 또는 N초 간의 CPU 프로파일을 제공하는 페이지func Trace(w http.ResponseWriter, r *http.Request)
// 주어진 몇 초 동안의 전체 스택 트레이스 (go tool pprof
가 아닌go tool trace
로 분석하는 full stack trace)func Cmdline(w http.ResponseWriter, r *http.Request)
// 명령줄 프로그램 인스턴스 나열하는 페이지func Symbol(w http.ResponseWriter, r *http.Request)
// "symbol" 프로파일 페이지