Source file src/cmd/compile/internal/gc/util.go

     1  // Copyright 2015 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package gc
     6  
     7  import (
     8  	"net/url"
     9  	"os"
    10  	"path/filepath"
    11  	"runtime"
    12  	"runtime/pprof"
    13  	tracepkg "runtime/trace"
    14  	"strings"
    15  
    16  	"cmd/compile/internal/base"
    17  )
    18  
    19  func profileName(fn, suffix string) string {
    20  	if strings.HasSuffix(fn, string(os.PathSeparator)) {
    21  		err := os.MkdirAll(fn, 0755)
    22  		if err != nil {
    23  			base.Fatalf("%v", err)
    24  		}
    25  	}
    26  	if fi, statErr := os.Stat(fn); statErr == nil && fi.IsDir() {
    27  		fn = filepath.Join(fn, url.PathEscape(base.Ctxt.Pkgpath)+suffix)
    28  	}
    29  	return fn
    30  }
    31  
    32  func startProfile() {
    33  	if base.Flag.CPUProfile != "" {
    34  		fn := profileName(base.Flag.CPUProfile, ".cpuprof")
    35  		f, err := os.Create(fn)
    36  		if err != nil {
    37  			base.Fatalf("%v", err)
    38  		}
    39  		if err := pprof.StartCPUProfile(f); err != nil {
    40  			base.Fatalf("%v", err)
    41  		}
    42  		base.AtExit(pprof.StopCPUProfile)
    43  	}
    44  	if base.Flag.MemProfile != "" {
    45  		if base.Flag.MemProfileRate != 0 {
    46  			runtime.MemProfileRate = base.Flag.MemProfileRate
    47  		}
    48  		const (
    49  			gzipFormat = 0
    50  			textFormat = 1
    51  		)
    52  		// compilebench parses the memory profile to extract memstats,
    53  		// which are only written in the legacy (text) pprof format.
    54  		// See golang.org/issue/18641 and runtime/pprof/pprof.go:writeHeap.
    55  		// gzipFormat is what most people want, otherwise
    56  		var format = textFormat
    57  		fn := base.Flag.MemProfile
    58  		if strings.HasSuffix(fn, string(os.PathSeparator)) {
    59  			err := os.MkdirAll(fn, 0755)
    60  			if err != nil {
    61  				base.Fatalf("%v", err)
    62  			}
    63  		}
    64  		if fi, statErr := os.Stat(fn); statErr == nil && fi.IsDir() {
    65  			fn = filepath.Join(fn, url.PathEscape(base.Ctxt.Pkgpath)+".memprof")
    66  			format = gzipFormat
    67  		}
    68  
    69  		f, err := os.Create(fn)
    70  
    71  		if err != nil {
    72  			base.Fatalf("%v", err)
    73  		}
    74  		base.AtExit(func() {
    75  			// Profile all outstanding allocations.
    76  			runtime.GC()
    77  			if err := pprof.Lookup("heap").WriteTo(f, format); err != nil {
    78  				base.Fatalf("%v", err)
    79  			}
    80  		})
    81  	} else {
    82  		// Not doing memory profiling; disable it entirely.
    83  		runtime.MemProfileRate = 0
    84  	}
    85  	if base.Flag.BlockProfile != "" {
    86  		f, err := os.Create(profileName(base.Flag.BlockProfile, ".blockprof"))
    87  		if err != nil {
    88  			base.Fatalf("%v", err)
    89  		}
    90  		runtime.SetBlockProfileRate(1)
    91  		base.AtExit(func() {
    92  			pprof.Lookup("block").WriteTo(f, 0)
    93  			f.Close()
    94  		})
    95  	}
    96  	if base.Flag.MutexProfile != "" {
    97  		f, err := os.Create(profileName(base.Flag.MutexProfile, ".mutexprof"))
    98  		if err != nil {
    99  			base.Fatalf("%v", err)
   100  		}
   101  		runtime.SetMutexProfileFraction(1)
   102  		base.AtExit(func() {
   103  			pprof.Lookup("mutex").WriteTo(f, 0)
   104  			f.Close()
   105  		})
   106  	}
   107  	if base.Flag.TraceProfile != "" {
   108  		f, err := os.Create(profileName(base.Flag.TraceProfile, ".trace"))
   109  		if err != nil {
   110  			base.Fatalf("%v", err)
   111  		}
   112  		if err := tracepkg.Start(f); err != nil {
   113  			base.Fatalf("%v", err)
   114  		}
   115  		base.AtExit(tracepkg.Stop)
   116  	}
   117  }
   118  

View as plain text