gitee.com/mirrors/Hugo-Go@v0.47.1/commands/benchmark.go (about) 1 // Copyright 2015 The Hugo Authors. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package commands 15 16 import ( 17 "os" 18 "runtime" 19 "runtime/pprof" 20 "time" 21 22 "github.com/spf13/cobra" 23 jww "github.com/spf13/jwalterweatherman" 24 ) 25 26 type benchmarkCmd struct { 27 benchmarkTimes int 28 cpuProfileFile string 29 memProfileFile string 30 31 *baseBuilderCmd 32 } 33 34 func (b *commandsBuilder) newBenchmarkCmd() *benchmarkCmd { 35 cmd := &cobra.Command{ 36 Use: "benchmark", 37 Short: "Benchmark Hugo by building a site a number of times.", 38 Long: `Hugo can build a site many times over and analyze the running process 39 creating a benchmark.`, 40 } 41 42 c := &benchmarkCmd{baseBuilderCmd: b.newBuilderCmd(cmd)} 43 44 cmd.Flags().StringVar(&c.cpuProfileFile, "cpuprofile", "", "path/filename for the CPU profile file") 45 cmd.Flags().StringVar(&c.memProfileFile, "memprofile", "", "path/filename for the memory profile file") 46 cmd.Flags().IntVarP(&c.benchmarkTimes, "count", "n", 13, "number of times to build the site") 47 cmd.Flags().Bool("renderToMemory", false, "render to memory (only useful for benchmark testing)") 48 49 cmd.RunE = c.benchmark 50 51 return c 52 } 53 54 func (c *benchmarkCmd) benchmark(cmd *cobra.Command, args []string) error { 55 cfgInit := func(c *commandeer) error { 56 return nil 57 } 58 59 comm, err := initializeConfig(true, false, &c.hugoBuilderCommon, c, cfgInit) 60 if err != nil { 61 return err 62 } 63 64 var memProf *os.File 65 if c.memProfileFile != "" { 66 memProf, err = os.Create(c.memProfileFile) 67 if err != nil { 68 return err 69 } 70 } 71 72 var cpuProf *os.File 73 if c.cpuProfileFile != "" { 74 cpuProf, err = os.Create(c.cpuProfileFile) 75 if err != nil { 76 return err 77 } 78 } 79 80 var memStats runtime.MemStats 81 runtime.ReadMemStats(&memStats) 82 memAllocated := memStats.TotalAlloc 83 mallocs := memStats.Mallocs 84 if cpuProf != nil { 85 pprof.StartCPUProfile(cpuProf) 86 } 87 88 t := time.Now() 89 for i := 0; i < c.benchmarkTimes; i++ { 90 if err = comm.resetAndBuildSites(); err != nil { 91 return err 92 } 93 } 94 totalTime := time.Since(t) 95 96 if memProf != nil { 97 pprof.WriteHeapProfile(memProf) 98 memProf.Close() 99 } 100 if cpuProf != nil { 101 pprof.StopCPUProfile() 102 cpuProf.Close() 103 } 104 105 runtime.ReadMemStats(&memStats) 106 totalMemAllocated := memStats.TotalAlloc - memAllocated 107 totalMallocs := memStats.Mallocs - mallocs 108 109 jww.FEEDBACK.Println() 110 jww.FEEDBACK.Printf("Average time per operation: %vms\n", int(1000*totalTime.Seconds()/float64(c.benchmarkTimes))) 111 jww.FEEDBACK.Printf("Average memory allocated per operation: %vkB\n", totalMemAllocated/uint64(c.benchmarkTimes)/1024) 112 jww.FEEDBACK.Printf("Average allocations per operation: %v\n", totalMallocs/uint64(c.benchmarkTimes)) 113 114 return nil 115 }