func initMemProf(OD string) { if *Flag_memprof { log.Println("memory profile enabled") AtExit(func() { fname := OD + "mem.pprof" f, err := os.Create(fname) defer f.Close() util.LogErr(err, "memory profile") // during cleanup, should not panic/exit log.Println("writing memory profile to", fname) util.LogErr(pprof.WriteHeapProfile(f), "memory profile") me := procSelfExe() outfile := fname + ".svg" saveCmdOutput(outfile, "go", "tool", "pprof", "-svg", "--inuse_objects", me, fname) }) } }
// Exec command and write output to outfile. func saveCmdOutput(outfile string, cmd string, args ...string) { log.Println("exec:", cmd, args, ">", outfile) out, err := exec.Command(cmd, args...).Output() // TODO: stderr is ignored if err != nil { log.Printf("exec %v %v: %v: %v", cmd, args, err, string(out)) } // on error: write anyway, clobbers output file. e := ioutil.WriteFile(outfile, out, 0666) util.LogErr(e, "writing", outfile) }
// SetOD sets the output directory where auto-saved files will be stored. func SetOD(od string, force bool) { if OD != "./" { log.Fatal("output directory already set to", OD) } OD = od if !strings.HasSuffix(OD, "/") { OD += "/" } log.Println("output directory:", OD) { // make OD wd, err := os.Getwd() util.FatalErr(err, "create output directory:") stat, err2 := os.Stat(wd) util.FatalErr(err2, "create output directory:") util.LogErr(os.Mkdir(od, stat.Mode())) // already exists is OK } // fail on non-empty OD f, err3 := os.Open(od) util.FatalErr(err3, "open output directory:") files, _ := f.Readdir(1) if !force && len(files) != 0 { log.Fatal(od, " not empty, clean it or force with -f") } // clean output dir if len(files) != 0 && OD != "." { log.Println("cleaning files in", OD) filepath.Walk(OD, func(path string, i os.FileInfo, err error) error { if path != OD { util.FatalErr(os.RemoveAll(path), "clean output directory:") } return nil }) } }