gitee.com/liuxuezhan/go-micro-v1.18.0@v1.0.0/debug/profile/pprof/pprof.go (about) 1 // Package pprof provides a pprof profiler 2 package pprof 3 4 import ( 5 "os" 6 "path/filepath" 7 "runtime" 8 "runtime/pprof" 9 "sync" 10 "time" 11 12 "gitee.com/liuxuezhan/go-micro-v1.18.0/debug/profile" 13 ) 14 15 type profiler struct { 16 opts profile.Options 17 18 sync.Mutex 19 running bool 20 exit chan bool 21 22 // where the cpu profile is written 23 cpuFile *os.File 24 // where the mem profile is written 25 memFile *os.File 26 } 27 28 func (p *profiler) writeHeap(f *os.File) { 29 defer f.Close() 30 31 t := time.NewTicker(time.Second * 30) 32 defer t.Stop() 33 34 for { 35 select { 36 case <-t.C: 37 runtime.GC() 38 pprof.WriteHeapProfile(f) 39 case <-p.exit: 40 return 41 } 42 } 43 } 44 45 func (p *profiler) Start() error { 46 p.Lock() 47 defer p.Unlock() 48 49 if p.running { 50 return nil 51 } 52 53 // create exit channel 54 p.exit = make(chan bool) 55 56 cpuFile := filepath.Join("/tmp", "cpu.pprof") 57 memFile := filepath.Join("/tmp", "mem.pprof") 58 59 if len(p.opts.Name) > 0 { 60 cpuFile = filepath.Join("/tmp", p.opts.Name+".cpu.pprof") 61 memFile = filepath.Join("/tmp", p.opts.Name+".mem.pprof") 62 } 63 64 f1, err := os.Create(cpuFile) 65 if err != nil { 66 return err 67 } 68 69 f2, err := os.Create(memFile) 70 if err != nil { 71 return err 72 } 73 74 // start cpu profiling 75 if err := pprof.StartCPUProfile(f1); err != nil { 76 return err 77 } 78 79 // write the heap periodically 80 go p.writeHeap(f2) 81 82 // set cpu file 83 p.cpuFile = f1 84 // set mem file 85 p.memFile = f2 86 87 p.running = true 88 89 return nil 90 } 91 92 func (p *profiler) Stop() error { 93 p.Lock() 94 defer p.Unlock() 95 96 select { 97 case <-p.exit: 98 return nil 99 default: 100 close(p.exit) 101 pprof.StopCPUProfile() 102 p.cpuFile.Close() 103 p.running = false 104 p.cpuFile = nil 105 p.memFile = nil 106 return nil 107 } 108 } 109 110 func NewProfile(opts ...profile.Option) profile.Profile { 111 var options profile.Options 112 for _, o := range opts { 113 o(&options) 114 } 115 p := new(profiler) 116 p.opts = options 117 return p 118 }