shithub: hugo

Download patch

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])
 }