go 언어에서 메모리 사용 프로파일링 하기.
By SeukWon Kang
이전에 cpu profile 하는 글을 썼지만 http://kasw.blogspot.kr/2015/02/go-profiling_4.html
이번에는 memory profile을 하기 위한 수정을 했습니다.
시작과 끝을 지정해야하는 cpu profile과는 달리 memory profile은 현상태의 snapshot을 떠내는 형태로 사용하게 됩니다.
프로파일을 위한 shell script는
//start
#!/usr/bin/env sh
PRGNAME="$1"
shift
go build ${PRGNAME}.go
./${PRGNAME} -memprofilename ${PRGNAME}.mprof $*
go tool pprof ${PRGNAME} ${PRGNAME}.mprof
rm ${PRGNAME}.mprof
//end
과 같고,
실제 프로그램에서 사용할때는
//start
package main
import (
"flag"
"fmt"
"log"
"math/rand"
"os"
"runtime"
"runtime/pprof"
"time"
)
func init() {
rand.Seed(time.Now().UnixNano())
runtime.GOMAXPROCS(runtime.NumCPU())
}
func writeHeapProfile(filename string) {
f, err := os.Create(filename)
if err != nil {
log.Fatalf("mem profile %v", err)
}
pprof.WriteHeapProfile(f)
f.Close()
}
func startCPUProfile(filename string) func() {
f, err := os.Create(filename)
if err != nil {
log.Fatalf("cpu profile %v", err)
}
pprof.StartCPUProfile(f)
return pprof.StopCPUProfile
}
func main() {
log.Printf("go # %v", runtime.NumGoroutine())
var cpuprofilename = flag.String("cpuprofilename", "", "cpu profile filename")
var memprofilename = flag.String("memprofilename", "", "memory profile filename")
flag.Parse()
args := flag.Args()
if *cpuprofilename != "" {
fn := startCPUProfile(*cpuprofilename)
defer fn()
}
sttime := time.Now()
doMain(args)
fmt.Printf("%v\n", time.Now().Sub(sttime))
log.Printf("go # %v", runtime.NumGoroutine())
if *memprofilename != "" {
writeHeapProfile(*memprofilename)
}
}
func doMain(args []string) {
fmt.Printf("%v\n", args)
}
//end
같은 형식으로 사용하면 됩니다.
memory profile 을 추가하면서 기존 cpu profile 하는 것도 같이 수정하였습니다.
전체 코드는 github https://github.com/kasworld/gotemplate 에 있습니다.