| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- package profile
- import (
- "os"
- "path/filepath"
- "runtime"
- "runtime/pprof"
- "bet24.com/log"
- )
- const (
- cpuMode = iota
- memMode
- mutexMode
- blockMode
- traceMode
- goroutineMode
- threadCreateMode
- )
- type Profile struct {
- // 分析模式
- mode int
- path string
- //内存配置文件采样速率,分析器将会在每分配指定的字节数量后对内存使用情况进行取样
- memProfileRate int
- closer func()
- stopped uint32
- namePrefix string
- }
- func NamePrefix(name string) func(*Profile) {
- return func(p *Profile) {
- p.namePrefix = name
- }
- }
- // CPUProfile enables cpu profiling.
- // It disables any previous profiling settings.
- func CPUProfile(p *Profile) { p.mode = cpuMode }
- // DefaultMemProfileRate is the default memory profiling rate.
- const DefaultMemProfileRate = 4096
- // MemProfile enables memory profiling.
- // It disables any previous profiling settings.
- func MemProfile(p *Profile) {
- p.memProfileRate = DefaultMemProfileRate
- p.mode = memMode
- }
- //GoRTProfile enables goroutine profiling
- func GoRTProfile(p *Profile) { p.mode = goroutineMode }
- //block enables goroutine profiling
- func BlockProfile(p *Profile) { p.mode = blockMode }
- //MutexProfile enables goroutine profiling
- func MutexProfile(p *Profile) { p.mode = mutexMode }
- // ProfilePath controls the base path where various profiling
- // files are written. If blank, the base path will be generated
- // by os.MkdirTemp.
- func ProfilePath(path string) func(*Profile) {
- return func(p *Profile) {
- p.path = path
- }
- }
- // Stop stops the profile and flushes any unwritten data.
- func (p *Profile) Stop() {
- p.closer()
- }
- // Start starts a new profiling session.
- // The caller should call the Stop method on the value returned
- // to cleanly stop profiling.
- func Start(options ...func(*Profile)) interface {
- Stop()
- } {
- var prof Profile
- for _, option := range options {
- option(&prof)
- }
- path, err := func() (string, error) {
- if p := prof.path; p != "" {
- return p, os.MkdirAll(p, 0777)
- }
- return os.MkdirTemp("", "profile")
- }()
- if err != nil {
- log.Fatal("profile: could not create initial output directory: %v", err)
- }
- logf := func(format string, args ...interface{}) {
- log.Debug(format, args...)
- }
- switch prof.mode {
- case cpuMode:
- fn := filepath.Join(path, prof.namePrefix+"cpu.pprof")
- f, err := os.Create(fn)
- if err != nil {
- log.Fatal("profile: could not create cpu profile %q: %v", fn, err)
- }
- logf("profile: cpu profiling enabled, %s", fn)
- pprof.StartCPUProfile(f)
- prof.closer = func() {
- pprof.StopCPUProfile()
- f.Close()
- logf("profile: cpu profiling disabled, %s", fn)
- }
- case memMode:
- fn := filepath.Join(path, prof.namePrefix+"mem.pprof")
- f, err := os.Create(fn)
- if err != nil {
- log.Fatal("profile: could not create memory profile %q: %v", fn, err)
- }
- old := runtime.MemProfileRate
- runtime.MemProfileRate = prof.memProfileRate
- logf("profile: memory profiling enabled (rate %d), %s", runtime.MemProfileRate, fn)
- prof.closer = func() {
- pprof.Lookup("heap").WriteTo(f, 0)
- f.Close()
- runtime.MemProfileRate = old
- logf("profile: memory profiling disabled, %s", fn)
- }
- case goroutineMode:
- fn := filepath.Join(path, prof.namePrefix+"goroutine.pprof")
- f, err := os.Create(fn)
- if err != nil {
- log.Fatal("profile: could not create goroutine profile %q: %v", fn, err)
- }
- logf("profile: goroutine profiling enabled, %s", fn)
- prof.closer = func() {
- pprof.Lookup("goroutine").WriteTo(f, 0)
- f.Close()
- logf("profile: goroutine profiling disabled, %s", fn)
- }
- case blockMode:
- fn := filepath.Join(path, prof.namePrefix+"block.pprof")
- f, err := os.Create(fn)
- if err != nil {
- log.Fatal("profile: could not create block profile %q: %v", fn, err)
- }
- logf("profile: block profiling enabled, %s", fn)
- prof.closer = func() {
- pprof.Lookup("block").WriteTo(f, 0)
- f.Close()
- logf("profile: block profiling disabled, %s", fn)
- }
- case mutexMode:
- fn := filepath.Join(path, prof.namePrefix+"mutex.pprof")
- f, err := os.Create(fn)
- if err != nil {
- log.Fatal("profile: could not create mutex profile %q: %v", fn, err)
- }
- logf("profile: mutex profiling enabled, %s", fn)
- prof.closer = func() {
- pprof.Lookup("mutex").WriteTo(f, 0)
- f.Close()
- logf("profile: mutex profiling disabled, %s", fn)
- }
- }
- return &prof
- }
|