github.com/mutagen-io/mutagen@v0.18.0-rc1/cmd/profile/profile.go (about) 1 package profile 2 3 import ( 4 "fmt" 5 "os" 6 "runtime" 7 "runtime/pprof" 8 ) 9 10 // Profile manages a CPU and heap profile. 11 type Profile struct { 12 // name is the name of the profile. 13 name string 14 // cpuProfile is the output file for the CPU profile. 15 cpuProfile *os.File 16 } 17 18 // New creates a new profile instance. The profiling begins immediately. 19 func New(name string) (*Profile, error) { 20 // Open the CPU profile output. 21 cpuProfile, err := os.Create(fmt.Sprintf("%s_cpu.prof", name)) 22 if err != nil { 23 return nil, fmt.Errorf("unable to create CPU profile: %w", err) 24 } 25 26 // Start CPU profiling. 27 if err := pprof.StartCPUProfile(cpuProfile); err != nil { 28 cpuProfile.Close() 29 return nil, fmt.Errorf("unable to start CPU profile: %w", err) 30 } 31 32 // Success. 33 return &Profile{ 34 name: name, 35 cpuProfile: cpuProfile, 36 }, nil 37 } 38 39 // Finalize terminates a profile and writes its measurements to disk in the 40 // current working directory. 41 func (p *Profile) Finalize() error { 42 // Close out the CPU profile. 43 pprof.StopCPUProfile() 44 if err := p.cpuProfile.Close(); err != nil { 45 return fmt.Errorf("unable to close CPU profile: %w", err) 46 } 47 48 // Run a GC cycle to update the heap profile statistics. 49 runtime.GC() 50 51 // Write a heap profile. 52 heapProfile, err := os.Create(fmt.Sprintf("%s_heap.prof", p.name)) 53 if err != nil { 54 return fmt.Errorf("unable to create heap profile: %w", err) 55 } 56 if err := pprof.WriteHeapProfile(heapProfile); err != nil { 57 heapProfile.Close() 58 return fmt.Errorf("unable to write heap profile: %w", err) 59 } 60 if err := heapProfile.Close(); err != nil { 61 return fmt.Errorf("unable to close heap profile: %w", err) 62 } 63 64 // Success. 65 return nil 66 }