ref: 48dbb593f7cc0dceb55d232ac198e82f3df1c964
parent: f0266e2ef3487bc57dd05402002fc816e3b40195
author: Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
date: Thu Jun 25 07:44:27 EDT 2020
commands: Add an option to print memory usage at intervals Use it with `hugo --print-mem
--- a/commands/commands.go
+++ b/commands/commands.go
@@ -212,6 +212,7 @@
memprofile string
mutexprofile string
traceprofile string
+ printm bool
// TODO(bep) var vs string
logging bool
@@ -299,6 +300,7 @@
cmd.Flags().BoolP("path-warnings", "", false, "print warnings on duplicate target paths etc.")
cmd.Flags().StringVarP(&cc.cpuprofile, "profile-cpu", "", "", "write cpu profile to `file`")
cmd.Flags().StringVarP(&cc.memprofile, "profile-mem", "", "", "write memory profile to `file`")
+ cmd.Flags().BoolVarP(&cc.printm, "print-mem", "", false, "print memory usage to screen at intervals")
cmd.Flags().StringVarP(&cc.mutexprofile, "profile-mutex", "", "", "write Mutex profile to `file`")
cmd.Flags().StringVarP(&cc.traceprofile, "trace", "", "", "write trace to `file` (not useful in general)")
--- a/commands/hugo.go
+++ b/commands/hugo.go
@@ -82,6 +82,7 @@
// Execute adds all child commands to the root command HugoCmd and sets flags appropriately.
// The args are usually filled with os.Args[1:].
func Execute(args []string) Response {
+
hugoCmd := newCommandsBuilder().addAll().build()
cmd := hugoCmd.getCommand()
cmd.SetArgs(args)
@@ -427,7 +428,37 @@
}
+func (c *commandeer) initMemTicker() func() {
+ memticker := time.NewTicker(5 * time.Second)
+ quit := make(chan struct{})
+ printMem := func() {
+ var m runtime.MemStats
+ runtime.ReadMemStats(&m)
+ fmt.Printf("\n\nAlloc = %v\nTotalAlloc = %v\nSys = %v\nNumGC = %v\n\n", formatByteCount(m.Alloc), formatByteCount(m.TotalAlloc), formatByteCount(m.Sys), m.NumGC)
+
+ }
+
+ go func() {
+ for {
+ select {
+ case <-memticker.C:
+ printMem()
+ case <-quit:
+ memticker.Stop()
+ printMem()
+ return
+ }
+
+ }
+ }()
+
+ return func() {
+ close(quit)
+ }
+}
+
func (c *commandeer) initProfiling() (func(), error) {
+
stopCPUProf, err := c.initCPUProfile()
if err != nil {
return nil, err
@@ -443,6 +474,11 @@
return nil, err
}
+ var stopMemTicker func()
+ if c.h.printm {
+ stopMemTicker = c.initMemTicker()
+ }
+
return func() {
c.initMemProfile()
@@ -456,6 +492,10 @@
if stopTraceProf != nil {
stopTraceProf()
}
+
+ if stopMemTicker != nil {
+ stopMemTicker()
+ }
}, nil
}
@@ -1174,4 +1214,18 @@
}
return name
+}
+
+func formatByteCount(b uint64) string {
+ const unit = 1000
+ if b < unit {
+ return fmt.Sprintf("%d B", b)
+ }
+ div, exp := int64(unit), 0
+ for n := b / unit; n >= unit; n /= unit {
+ div *= unit
+ exp++
+ }
+ return fmt.Sprintf("%.1f %cB",
+ float64(b)/float64(div), "kMGTPE"[exp])
}