github.com/goproxy0/go@v0.0.0-20171111080102-49cc0c489d2c/doc/diagnostics.html (about)

     1  <!--{
     2  	"Title": "Diagnostics",
     3  	"Template": true
     4  }-->
     5  
     6  <h2 id="introduction">Introduction</h2>
     7  
     8  <p>
     9  The Go ecosystem provides a large suite of APIs and tools to
    10  diagnose logic and performance problems in Go programs. This page
    11  summarizes the available tools and helps Go users pick the right one
    12  for their specific problem.
    13  </p>
    14  
    15  <p>
    16  Diagnostics solutions can be categorized into the following groups:
    17  </p>
    18  
    19  <ul>
    20  <li><strong>Profiling</strong>: Profiling tools analyze the complexity and costs of a
    21  Go program such as its memory usage and frequently called
    22  functions to identify the expensive sections of a Go program.</li>
    23  <li><strong>Tracing</strong>: Tracing is a way to instrument code to analyze latency
    24  throughout the lifecycle of a call or user request. Traces provide an
    25  overview of how much latency each component contributes to the overall
    26  latency in a system. Traces can span multiple Go processes.</li>
    27  <li><strong>Debugging</strong>: Debugging allows us to pause a Go program and examine
    28  its execution. Program state and flow can be verified with debugging.</li>
    29  <li><strong>Runtime statistics and events</strong>: Collection and analysis of runtime stats and events
    30  provides a high-level overview of the health of Go programs. Spikes/dips of metrics
    31  helps us to identify changes in throughput, utilization, and performance.</li>
    32  </ul>
    33  
    34  <p>
    35  Note: Some diagnostics tools may interfere with each other. For example, precise
    36  memory profiling skews CPU profiles and goroutine blocking profiling affects scheduler
    37  trace. Use tools in isolation to get more precise info.
    38  </p>
    39  
    40  <h2 id="profiling">Profiling</h2>
    41  
    42  <p>
    43  Profiling is useful for identifying expensive or frequently called sections
    44  of code. The Go runtime provides <a href="https://golang.org/pkg/runtime/pprof/">
    45  profiling data</a> in the format expected by the
    46  <a href="https://github.com/google/pprof/blob/master/doc/pprof.md">pprof visualization tool</a>.
    47  The profiling data can be collected during testing
    48  via <code>go test</code> or endpoints made available from the <a href="/pkg/net/http/pprof/">
    49  net/http/pprof</a> package. Users need to collect the profiling data and use pprof tools to filter
    50  and visualize the top code paths.
    51  </p>
    52  
    53  <p>Predefined profiles provided by the <a href="/pkg/runtime/pprof">runtime/pprof</a> package:</p>
    54  
    55  <ul>
    56  <li>
    57  <strong>cpu</strong>: CPU profile determines where a program spends
    58  its time while actively consuming CPU cycles (as opposed to while sleeping or waiting for I/O).
    59  </li>
    60  <li>
    61  <strong>heap</strong>: Heap profile reports memory allocation samples;
    62  used to monitor current and historical memory usage, and to check for memory leaks.
    63  </li>
    64  <li>
    65  <strong>threadcreate</strong>: Thread creation profile reports the sections
    66  of the program that lead the creation of new OS threads.
    67  </li>
    68  <li>
    69  <strong>goroutine</strong>: Goroutine profile reports the stack traces of all current goroutines.
    70  </li>
    71  <li>
    72  <strong>block</strong>: Block profile shows where goroutines block waiting on synchronization
    73  primitives (including timer channels). Block profile is not enabled by default;
    74  use <code>runtime.SetBlockProfileRate</code> to enable it.
    75  </li>
    76  <li>
    77  <strong>mutex</strong>: Mutex profile reports the lock contentions. When you think your
    78  CPU is not fully utilized due to a mutex contention, use this profile. Mutex profile
    79  is not enabled by default, see <code>runtime.SetMutexProfileFraction</code> to enable it.
    80  </li>
    81  </ul>
    82  
    83  
    84  <p><strong>What other profilers can I use to profile Go programs?</strong></p>
    85  
    86  <p>
    87  On Linux, <a href="https://perf.wiki.kernel.org/index.php/Tutorial">perf tools</a>
    88  can be used for profiling Go programs. Perf can profile
    89  and unwind cgo/SWIG code and kernel, so it can be useful to get insights into
    90  native/kernel performance bottlenecks. On macOS,
    91  <a href="https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/InstrumentsUserGuide/">Instruments</a>
    92  suite can be used profile Go programs.
    93  </p>
    94  
    95  <p><strong>Can I profile my production services?</strong></p>
    96  
    97  <p>Yes. It is safe to profile programs in production, but enabling
    98  some profiles (e.g. the CPU profile) adds cost. You should expect to
    99  see performance downgrade. The performance penalty can be estimated
   100  by measuring the overhead of the profiler before turning it on in
   101  production.
   102  </p>
   103  
   104  <p>
   105  You may want to periodically profile your production services.
   106  Especially in a system with many replicas of a single process, selecting
   107  a random replica periodically is a safe option.
   108  Select a production process, profile it for
   109  X seconds for every Y seconds and save the results for visualization and
   110  analysis; then repeat periodically. Results may be manually and/or automatically
   111  reviewed to find problems.
   112  Collection of profiles can interfere with each other,
   113  so it is recommended to collect only a single profile at a time.
   114  </p>
   115  
   116  <p>
   117  <strong>What are the best ways to visualize the profiling data?</strong>
   118  </p>
   119  
   120  <p>
   121  The Go tools provide text, graph, and <a href="http://valgrind.org/docs/manual/cl-manual.html">callgrind</a>
   122  visualization of the profile data via
   123  <code><a href="https://github.com/google/pprof/blob/master/doc/pprof.md">go tool pprof</a></code>.
   124  Read <a href="https://blog.golang.org/profiling-go-programs">Profiling Go programs</a>
   125  to see them in action.
   126  </p>
   127  
   128  <p>
   129  <img width="800" src="https://storage.googleapis.com/golangorg-assets/pprof-text.png">
   130  <br>
   131  <small>Listing of the most expensive calls as text.</small>
   132  </p>
   133  
   134  <p>
   135  <img width="800" src="https://storage.googleapis.com/golangorg-assets/pprof-dot.png">
   136  <br>
   137  <small>Visualization of the most expensive calls as a graph.</small>
   138  </p>
   139  
   140  <p>Weblist view displays the expensive parts of the source line by line in
   141  an HTML page. In the following example, 530ms is spent in the
   142  <code>runtime.concatstrings</code> and cost of each line is presented
   143  in the listing.</p>
   144  
   145  <p>
   146  <img width="800" src="https://storage.googleapis.com/golangorg-assets/pprof-weblist.png">
   147  <br>
   148  <small>Visualization of the most expensive calls as weblist.</small>
   149  </p>
   150  
   151  <p>
   152  Another way to visualize profile data is a <a href="https://github.com/uber/go-torch">flame graph</a>.
   153  Flame graphs allow you to move in a specific ancestry path, so you can zoom
   154  in/out specific sections of code more easily.
   155  </p>
   156  
   157  <p>
   158  <img width="800" src="https://storage.googleapis.com/golangorg-assets/flame.png">
   159  <br>
   160  <small>Flame graphs offers visualization to spot the most expensive code-paths.</small>
   161  </p>
   162  
   163  <p><strong>Am I restricted to the built-in profiles?</strong></p>
   164  
   165  <p>
   166  Additionally to what is provided by the runtime, Go users can create
   167  their custom profiles via <a href="/pkg/runtime/pprof/#Profile">pprof.Profile</a>
   168  and use the existing tools to examine them.
   169  </p>
   170  
   171  <p><strong>Can I serve the profiler handlers (/debug/pprof/...) on a different path and port?</strong></p>
   172  
   173  <p>
   174  Yes. The <code>net/http/pprof</code> package registers its handlers to the default
   175  mux by default, but you can also register them yourself by using the handlers
   176  exported from the package.
   177  </p>
   178  
   179  <p>
   180  For example, the following example will serve the pprof.Profile
   181  handler on :7777 at /pprof/profile:
   182  </p>
   183  
   184  <p>
   185  <pre>
   186  mux := http.NewServeMux()
   187  mux.HandleFunc("/custom_debug_path/profile", pprof.Profile)
   188  http.ListenAndServe(":7777", mux)
   189  </pre>
   190  </p>
   191  
   192  <h2 id="tracing">Tracing</h2>
   193  
   194  <p>
   195  Tracing is a way to instrument code to analyze latency throughout the
   196  lifecycle of a chain of calls. Go provides
   197  <a href="https://godoc.org/golang.org/x/net/trace">golang.org/x/net/trace</a>
   198  package as a minimal tracing backend per Go node and provides a minimal
   199  instrumentation library with a simple dashboard. Go also provides
   200  an execution tracer to trace the runtime events within an interval.
   201  </p>
   202  
   203  <p>Tracing enables us to:</p>
   204  
   205  <ul>
   206  <li>Instrument and profile application latency in a Go process.</li>
   207  <li>Measure the cost of specific calls in a long chain of calls.</li>
   208  <li>Figure out the utilization and performance improvements.
   209  Bottlenecks are not always obvious without tracing data.</li>
   210  </ul>
   211  
   212  <p>
   213  In monolithic systems, it's relatively easy to collect diagnostic data
   214  from the building blocks of a program. All modules live within one
   215  process and share common resources to report logs, errors, and other
   216  diagnostic information. Once your system grows beyond a single process and
   217  starts to become distributed, it becomes harder to follow a call starting
   218  from the front-end web server to all of its back-ends until a response is
   219  returned back to the user. This is where distributed tracing plays a big
   220  role to instrument and analyze your production systems.
   221  </p>
   222  
   223  <p>
   224  Distributed tracing is a way to instrument code to analyze latency throughout
   225  the lifecycle of a user request. When a system is distributed and when
   226  conventional profiling and debugging tools don’t scale, you might want
   227  to use distributed tracing tools to analyze the performance of your user
   228  requests and RPCs.
   229  </p>
   230  
   231  <p>Distributed tracing enables us to:</p>
   232  
   233  <ul>
   234  <li>Instrument and profile application latency in a large system.</li>
   235  <li>Track all RPCs within the lifecycle of a user request and see integration issues
   236  that are only visible in production.</li>
   237  <li>Figure out performance improvements that can be applied to our systems.
   238  Many bottlenecks are not obvious before the collection of tracing data.</li>
   239  </ul>
   240  
   241  <p>The Go ecosystem provides various distributed tracing libraries per tracing system
   242  and backend-agnostic ones.</p>
   243  
   244  
   245  <p><strong>Is there a way to automatically intercept each function call and create traces?</strong></p>
   246  
   247  <p>
   248  Go doesn’t provide a way to automatically intercept every function call and create
   249  trace spans. You need to manually instrument your code to create, end, and annotate spans.
   250  </p>
   251  
   252  <p><strong>How should I propagate trace headers in Go libraries?</strong></p>
   253  
   254  <p>
   255  You can propagate trace identifiers and tags in the <code>context.Context</code>.
   256  There is no canonical trace key or common representation of trace headers
   257  in the industry yet. Each tracing provider is responsible for providing propagation
   258  utilities in their Go libraries.
   259  </p>
   260  
   261  <p>
   262  <strong>What other low-level events from the standard library or
   263  runtime can be included in a trace?</strong>
   264  </p>
   265  
   266  <p>
   267  The standard library and runtime are trying to expose several additional APIs
   268  to notify on low level internal events. For example, httptrace.ClientTrace
   269  provides APIs to follow low-level events in the life cycle of an outgoing request.
   270  There is an ongoing effort to retrieve low-level runtime events from
   271  the runtime execution tracer and allow users to define and record their user events.
   272  </p>
   273  
   274  <h2 id="debugging">Debugging</h2>
   275  
   276  <p>
   277  Debugging is the process of identifying why a program misbehaves.
   278  Debuggers allow us to understand a program’s execution flow and current state.
   279  There are several styles of debugging; this section will only focus on attaching
   280  a debugger to a program and core dump debugging.
   281  </p>
   282  
   283  <p>Go users mostly use the following debuggers:</p>
   284  
   285  <ul>
   286  <li>
   287  <a href="https://github.com/derekparker/delve">Delve</a>:
   288  Delve is a debugger for the Go programming language. It has
   289  support for Go’s runtime concepts and built-in types. Delve is
   290  trying to be a fully featured reliable debugger for Go programs.
   291  </li>
   292  <li>
   293  <a href="https://golang.org/doc/gdb">GDB</a>:
   294  Go provides GDB support via the standard Go compiler and Gccgo.
   295  The stack management, threading, and runtime contain aspects that differ
   296  enough from the execution model GDB expects that they can confuse the
   297  debugger, even when the program is compiled with gccgo. Even though
   298  GDB can be used to debug Go programs, it is not ideal and may
   299  create confusion.
   300  </li>
   301  </ul>
   302  
   303  <p><strong>How well do debuggers work with Go programs?</strong></p>
   304  
   305  <p>
   306  As of Go 1.9, the DWARF info generated by the gc compiler is not complete
   307  and sometimes makes debugging harder. There is an ongoing effort to improve the
   308  DWARF information to help the debuggers display more accurate information.
   309  Until those improvements are in you may prefer to disable compiler
   310  optimizations during development for more accuracy. To disable optimizations,
   311  use the "-N -l" compiler flags. For example, the following command builds
   312  a package with no compiler optimizations:
   313  
   314  <p>
   315  <pre>
   316  $ go build -gcflags="-N -l"
   317  </pre>
   318  </p>
   319  
   320  <p>
   321  As of Go 1.10, the Go binaries will have the required DWARF information
   322  for accurate debugging. To enable the DWARF improvements, use the following
   323  compiler flags and use GDB until Delve supports location lists:
   324  </p>
   325  
   326  <p>
   327  <pre>
   328  $ go build -gcflags="-dwarflocationlists=true"
   329  </pre>
   330  </p>
   331  
   332  <p><strong>What’s the recommended debugger user interface?</strong></p>
   333  
   334  <p>
   335  Even though both delve and gdb provides CLIs, most editor integrations
   336  and IDEs provides debugging-specific user interfaces. Please refer to
   337  the <a href="/doc/editors.html">editors guide</a> to see the options
   338  with debugger UI support.
   339  </p>
   340  
   341  <p><strong>Is it possible to do postmortem debugging with Go programs?</strong></p>
   342  
   343  <p>
   344  A core dump file is a file that contains the memory dump of a running
   345  process and its process status. It is primarily used for post-mortem
   346  debugging of a program and to understand its state
   347  while it is still running. These two cases make debugging of core
   348  dumps a good diagnostic aid to postmortem and analyze production
   349  services. It is possible to obtain core files from Go programs and
   350  use delve or gdb to debug, see the
   351  <a href="https://golang.org/wiki/CoreDumpDebugging">core dump debugging</a>
   352  page for a step-by-step guide.
   353  </p>
   354  
   355  <h2 id="runtime">Runtime statistics and events</h2>
   356  
   357  <p>
   358  The runtime provides stats and reporting of internal events for
   359  users to diagnose performance and utilization problems at the
   360  runtime level.
   361  </p>
   362  
   363  <p>
   364  Users can monitor these stats to better understand the overall
   365  health and performance of Go programs.
   366  Some frequently monitored stats and states:
   367  </p>
   368  
   369  <ul>
   370  <li><code><a href="/pkg/runtime/#ReadMemStats">runtime.ReadMemStats</a></code>
   371  reports the metrics related to heap
   372  allocation and garbage collection. Memory stats are useful for
   373  monitoring how much memory resources a process is consuming,
   374  whether the process can utilize memory well, and to catch
   375  memory leaks.</li>
   376  <li><code><a href="/pkg/runtime/debug/#ReadGCStats">debug.ReadGCStats</a></code>
   377  reads statistics about garbage collection.
   378  It is useful to see how much of the resources are spent on GC pauses.
   379  It also reports a timeline of garbage collector pauses and pause time percentiles.</li>
   380  <li><code><a href="/pkg/runtime/debug/#Stack">debug.Stack</a></code>
   381  returns the current stack trace. Stack trace
   382  is useful to see how many goroutines are currently running,
   383  what they are doing, and whether they are blocked or not.</li>
   384  <li><code><a href="/pkg/runtime/debug/#WriteHeapDump">debug.WriteHeapDump</a></code>
   385  suspends the execution of all goroutines
   386  and allows you to dump the heap to a file. A heap dump is a
   387  snapshot of a Go process' memory at a given time. It contains all
   388  allocated objects as well as goroutines, finalizers, and more.</li>
   389  <li><code><a href="/pkg/runtime#NumGoroutine">runtime.NumGoroutine</a></code>
   390  returns the number of current goroutines.
   391  The value can be monitored to see whether enough goroutines are
   392  utilized or to detect the goroutine leaks.</li>
   393  </ul>
   394  
   395  <h3 id="execution-tracer">Execution tracer</h3>
   396  
   397  <p>Go comes with a runtime execution tracer to capture a wide range
   398  of runtime events. Scheduling, syscall, garbage collections,
   399  heap size, and other events are collected by runtime and available
   400  for visualization by the go tool trace. Execution tracer is a tool
   401  to detect latency and utilization problems. You can examine how well
   402  the CPU is utilized, and when networking or syscalls are a cause of
   403  preemption for the goroutines.</p>
   404  
   405  <p>Tracer is useful to:</p>
   406  <ul>
   407  <li>Understand how your goroutines execute.</li>
   408  <li>Understand some of the core runtime events such as GC runs.</li>
   409  <li>Identify poorly parallelized execution.</li>
   410  </ul>
   411  
   412  <p>However, it is not great for identifying hot spots such as
   413  analyzing the cause of excessive memory or CPU usage.
   414  Use profiling tools instead first to address them.</p>
   415  
   416  <p>
   417  <img width="800" src="https://storage.googleapis.com/golangorg-assets/tracer-lock.png">
   418  </p>
   419  
   420  <p>Above, the go tool trace visualization shows the execution started
   421  fine, and then it became serialized. It suggests that there might
   422  be lock contention for a shared resource that creates a bottleneck.</p>
   423  
   424  <p>See <a href="https://golang.org/cmd/trace/"><code>go tool trace</code></a>
   425  to collect and analyze runtime traces.
   426  </p>
   427  
   428  <h3 id="godebug">GODEBUG</h3>
   429  
   430  <p>Runtime also emits events and information if
   431  <a href="https://golang.org/pkg/runtime/#hdr-Environment_Variables">GODEBUG</a>
   432  environmental variable is set accordingly.</p>
   433  
   434  <ul>
   435  <li>GODEBUG=gctrace=1 prints garbage collector events at
   436  the event of collection, summarizing the amount of memory collected
   437  and the length of the pause.</li>
   438  <li>GODEBUG=schedtrace=X prints scheduling events at every X milliseconds.</li>
   439  </ul>