From 8e8b595a73f8b4b22b7d062837863a513640cab7 Mon Sep 17 00:00:00 2001 From: siddharth ravikumar Date: Sun, 25 Dec 2022 14:56:58 -0500 Subject: fern: add cpu and memory profiling --- fern.go | 51 +++++++++++++++++++++++++++++++++++++++++++++++++-- version/version.go | 2 +- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/fern.go b/fern.go index ea92311..3e288ac 100644 --- a/fern.go +++ b/fern.go @@ -46,7 +46,12 @@ package main import ( "flag" "fmt" + "log" "os" + "path" + "runtime" + "runtime/pprof" + "time" "ricketyspace.net/fern/config" "ricketyspace.net/fern/db" @@ -59,6 +64,8 @@ var pState *state.ProcessState var vFlag *bool var rFlag *bool +var pFlag *string +var profileSuffix string func init() { var err error @@ -83,6 +90,8 @@ func init() { // Parse args. vFlag = flag.Bool("version", false, "Print version") rFlag = flag.Bool("run", false, "Run fern") + pFlag = flag.String("prof", "", + "Write cpu and memory profiles to the specified directory") flag.Parse() if *vFlag { @@ -92,16 +101,54 @@ func init() { if !*rFlag { printUsage(2) } + if *pFlag != "" { + profileSuffix = fmt.Sprintf("%d.prof", time.Now().UnixMilli()) + } + + // Setup logger. + log.SetFlags(0) } func printUsage(exit int) { - fmt.Printf("fern [ -run | -version ]\n") + fmt.Printf("fern [ -run [ -prof DIR ] | -version ]\n") flag.PrintDefaults() os.Exit(exit) } func main() { - defer pState.DB.Write() // Write database to disk before returning. + // Setup CPU and memory profiling if enabled. + if *pFlag != "" { + // CPU profiling. + cn := path.Join(*pFlag, "cpu."+profileSuffix) + cf, err := os.Create(cn) + if err != nil { + log.Fatal("could not create CPU profile: ", err) + } + defer cf.Close() + if err := pprof.StartCPUProfile(cf); err != nil { + log.Fatal("could not start CPU profile: ", err) + } + defer pprof.StopCPUProfile() + + // Memory profiling. + mn := path.Join(*pFlag, "mem."+profileSuffix) + mf, err := os.Create(mn) + if err != nil { + log.Fatal("could not create memory profile: ", err) + } + defer mf.Close() + defer func() { + runtime.GC() + if err := pprof.WriteHeapProfile(mf); err != nil { + log.Fatal("could not write memory profile: ", err) + } + }() + log.Printf("Profiling enabled. CPU and memory profiles"+ + " will be written to %s and %s", cn, mn) + } + + // Write database to disk before returning. + defer pState.DB.Write() // Process all feeds. processing := 0 diff --git a/version/version.go b/version/version.go index 852e71f..1256ce6 100644 --- a/version/version.go +++ b/version/version.go @@ -3,4 +3,4 @@ package version -const Version = "0.6.0" +const Version = "0.6.1.dev" -- cgit v1.2.3