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(func() {
    43  			pprof.StopCPUProfile()
    44  			if err = f.Close(); err != nil {
    45  				base.Fatalf("error closing cpu profile: %v", err)
    46  			}
    47  		})
    48  	}
    49  	if base.Flag.MemProfile != "" {
    50  		if base.Flag.MemProfileRate != 0 {
    51  			runtime.MemProfileRate = base.Flag.MemProfileRate
    52  		}
    53  		const (
    54  			gzipFormat = 0
    55  			textFormat = 1
    56  		)
    57  		// compilebench parses the memory profile to extract memstats,
    58  		// which are only written in the legacy (text) pprof format.
    59  		// See golang.org/issue/18641 and runtime/pprof/pprof.go:writeHeap.
    60  		// gzipFormat is what most people want, otherwise
    61  		var format = textFormat
    62  		fn := base.Flag.MemProfile
    63  		if strings.HasSuffix(fn, string(os.PathSeparator)) {
    64  			err := os.MkdirAll(fn, 0755)
    65  			if err != nil {
    66  				base.Fatalf("%v", err)
    67  			}
    68  		}
    69  		if fi, statErr := os.Stat(fn); statErr == nil && fi.IsDir() {
    70  			fn = filepath.Join(fn, url.PathEscape(base.Ctxt.Pkgpath)+".memprof")
    71  			format = gzipFormat
    72  		}
    73  
    74  		f, err := os.Create(fn)
    75  
    76  		if err != nil {
    77  			base.Fatalf("%v", err)
    78  		}
    79  		base.AtExit(func() {
    80  			// Profile all outstanding allocations.
    81  			runtime.GC()
    82  			if err := pprof.Lookup("heap").WriteTo(f, format); err != nil {
    83  				base.Fatalf("%v", err)
    84  			}
    85  			if err = f.Close(); err != nil {
    86  				base.Fatalf("error closing memory profile: %v", err)
    87  			}
    88  		})
    89  	} else {
    90  		// Not doing memory profiling; disable it entirely.
    91  		runtime.MemProfileRate = 0
    92  	}
    93  	if base.Flag.BlockProfile != "" {
    94  		f, err := os.Create(profileName(base.Flag.BlockProfile, ".blockprof"))
    95  		if err != nil {
    96  			base.Fatalf("%v", err)
    97  		}
    98  		runtime.SetBlockProfileRate(1)
    99  		base.AtExit(func() {
   100  			pprof.Lookup("block").WriteTo(f, 0)
   101  			f.Close()
   102  		})
   103  	}
   104  	if base.Flag.MutexProfile != "" {
   105  		f, err := os.Create(profileName(base.Flag.MutexProfile, ".mutexprof"))
   106  		if err != nil {
   107  			base.Fatalf("%v", err)
   108  		}
   109  		runtime.SetMutexProfileFraction(1)
   110  		base.AtExit(func() {
   111  			pprof.Lookup("mutex").WriteTo(f, 0)
   112  			f.Close()
   113  		})
   114  	}
   115  	if base.Flag.TraceProfile != "" {
   116  		f, err := os.Create(profileName(base.Flag.TraceProfile, ".trace"))
   117  		if err != nil {
   118  			base.Fatalf("%v", err)
   119  		}
   120  		if err := tracepkg.Start(f); err != nil {
   121  			base.Fatalf("%v", err)
   122  		}
   123  		base.AtExit(func() {
   124  			tracepkg.Stop()
   125  			if err = f.Close(); err != nil {
   126  				base.Fatalf("error closing trace profile: %v", err)
   127  			}
   128  		})
   129  	}
   130  }
   131  

View as plain text