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>