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  }