<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Chapter 16 Tooling and Observability on Go: Under the Hood</title>
    <link>/en/part5toolchain/ch16tools/</link>
    <description>Recent content in Chapter 16 Tooling and Observability on Go: Under the Hood</description>
    <generator>Hugo</generator>
    <language>en</language>
    <atom:link href="/en/part5toolchain/ch16tools/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>16.1 Runtime Deadlock Detection</title>
      <link>/en/part5toolchain/ch16tools/deadlock/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>/en/part5toolchain/ch16tools/deadlock/</guid>
      <description>&lt;h1 id=&#34;161-runtime-deadlock-detection&#34;&gt;16.1 Runtime Deadlock Detection&lt;/h1&gt;&#xA;&lt;p&gt;&lt;code&gt;fatal error: all goroutines are asleep - deadlock!&lt;/code&gt;, almost every Go programmer has seen this error. It&#xA;comes from the runtime&amp;rsquo;s built-in deadlock detector. This section first makes clear how it decides and when&#xA;it fires, then turns to something more important: what it can guarantee in theory, and what it is&#xA;&lt;strong&gt;structurally unable to detect&lt;/strong&gt;. The latter is the root of many production &amp;ldquo;hang&amp;rdquo; mysteries; understanding&#xA;it is worth more than memorizing that error message.&lt;/p&gt;</description>
    </item>
    <item>
      <title>16.2 Race Detection</title>
      <link>/en/part5toolchain/ch16tools/race/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>/en/part5toolchain/ch16tools/race/</guid>
      <description>&lt;h1 id=&#34;162-race-detection&#34;&gt;16.2 Race Detection&lt;/h1&gt;&#xA;&lt;p&gt;A data race is the most insidious and hardest-to-reproduce class of bug in concurrent programs. Its definition is short: if two goroutines&#xA;access the same memory address concurrently, at least one of them is a write, and no synchronization orders the two, then the program&amp;rsquo;s behavior&#xA;is undefined (&lt;a href=&#34;/en/part3concurrency/ch11sync/mem/&#34;&gt;11.9&lt;/a&gt;). &amp;ldquo;Undefined&amp;rdquo; is not as gentle as &amp;ldquo;you read a stale value&amp;rdquo;;&#xA;it means the compiler and the processor are both allowed to perform surprising reorderings, and the result may be right one time and wrong the next, may appear only under stress&#xA;load, only on a certain CPU, only in a certain version, just once in a while. There is no hope of catching this kind of bug by human code review. Go&amp;rsquo;s&#xA;&lt;strong&gt;race detector&lt;/strong&gt; (&lt;code&gt;-race&lt;/code&gt;) is exactly the tool that turns this from &amp;ldquo;reproduce it by luck&amp;rdquo; into &amp;ldquo;run it once and it tells you&amp;rdquo;. This section&#xA;explains its principle, the algorithmic cost behind it, and the two capability boundaries you must keep in mind.&lt;/p&gt;</description>
    </item>
    <item>
      <title>16.3 Execution Tracing</title>
      <link>/en/part5toolchain/ch16tools/trace/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>/en/part5toolchain/ch16tools/trace/</guid>
      <description>&lt;h1 id=&#34;163-execution-tracing&#34;&gt;16.3 Execution Tracing&lt;/h1&gt;&#xA;&lt;p&gt;&lt;code&gt;pprof&lt;/code&gt; (&lt;a href=&#34;.././perf&#34;&gt;16.5&lt;/a&gt;) answers the question &amp;ldquo;which functions is the time being spent in&amp;rdquo;. It aggregates CPU samples taken over a window into a call tree and tells you that &lt;code&gt;json.Marshal&lt;/code&gt; accounts for 30% of the CPU. But it cannot answer another class of question: a request took 50ms, and for 45ms of it the goroutine &lt;strong&gt;was not running at all&lt;/strong&gt;, it was waiting. Waiting for what? A lock? The network? Interrupted by GC? Or it wanted to run but had no P available (&lt;a href=&#34;/en/part3concurrency/ch09sched/steal/&#34;&gt;9.2&lt;/a&gt;)? A CPU profile knows nothing about &amp;ldquo;waiting&amp;rdquo;, because it only samples the stack that is currently executing, and a blocked goroutine is on no CPU at all, so it is naturally never sampled.&lt;/p&gt;</description>
    </item>
    <item>
      <title>16.4 Testing Code</title>
      <link>/en/part5toolchain/ch16tools/testing/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>/en/part5toolchain/ch16tools/testing/</guid>
      <description>&lt;h1 id=&#34;164-testing-code&#34;&gt;16.4 Testing Code&lt;/h1&gt;&#xA;&lt;p&gt;Testing in Go is not a bolt-on, it is a first-class citizen of the language toolchain. &lt;code&gt;go test&lt;/code&gt; is built in, the &lt;code&gt;testing&lt;/code&gt; package is standard, and convention replaces configuration. This set of design choices has deeply shaped Go&amp;rsquo;s engineering culture: in other languages, &amp;ldquo;whether to write tests at all, and which framework to use&amp;rdquo; is a decision that requires weighing trade-offs; in Go it is the default action. This section explains how this machinery runs, why it was designed this way, and how it grew from unit testing all the way to Go 1.18 fuzzing.&lt;/p&gt;</description>
    </item>
    <item>
      <title>16.5 Benchmarking and Performance Profiling</title>
      <link>/en/part5toolchain/ch16tools/perf/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>/en/part5toolchain/ch16tools/perf/</guid>
      <description>&lt;h1 id=&#34;165-benchmarking-and-performance-profiling&#34;&gt;16.5 Benchmarking and Performance Profiling&lt;/h1&gt;&#xA;&lt;p&gt;The first principle of optimization is to measure before you act. Guessing at bottlenecks by intuition usually guesses wrong; the real hot spots are often not where you think they are. Go builds every tool this discipline requires straight into the toolchain: benchmarks answer &amp;ldquo;how fast,&amp;rdquo; profiling answers &amp;ldquo;where is it slow, where does the memory go,&amp;rdquo; and &lt;code&gt;benchstat&lt;/code&gt; uses statistics to answer &amp;ldquo;did this change actually make things faster, or is it just noise.&amp;rdquo; This section explains all three tools thoroughly and strings them into a measurement-driven loop of &amp;ldquo;profile to find the hot spot, change, benchmark to verify.&amp;rdquo; One level up, this loop joins with PGO (&lt;a href=&#34;../../ch15compile/optimize&#34;&gt;15.3&lt;/a&gt;) and execution tracing (&lt;a href=&#34;.././trace&#34;&gt;16.3&lt;/a&gt;) to form Go&amp;rsquo;s complete performance-engineering methodology.&lt;/p&gt;</description>
    </item>
    <item>
      <title>16.6 Runtime Metrics</title>
      <link>/en/part5toolchain/ch16tools/metric/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>/en/part5toolchain/ch16tools/metric/</guid>
      <description>&lt;h1 id=&#34;166-runtime-metrics&#34;&gt;16.6 Runtime Metrics&lt;/h1&gt;&#xA;&lt;p&gt;Profiling (&lt;a href=&#34;.././perf&#34;&gt;16.5&lt;/a&gt;) and tracing (&lt;a href=&#34;.././trace&#34;&gt;16.3&lt;/a&gt;) belong to the family of &amp;ldquo;pull it in to diagnose when something goes wrong&amp;rdquo; tools: they cost a fair amount, produce a lot of output, and suit the case where you already suspect a problem somewhere and want to capture a window of time or a single request to look at closely. But in production the more common question is not &amp;ldquo;profile this for me right now&amp;rdquo;; it is &amp;ldquo;has this service been healthy over the past week, when did it start degrading, and should we page someone at midnight?&amp;rdquo; Answering questions like these does not rely on a one-off deep dive. It relies on &lt;strong&gt;continuous, low-cost, long-retainable numbers&lt;/strong&gt;: how big the heap is, how often GC runs, whether the goroutine count is climbing, whether the tail of scheduling latency is rising. These numbers are &lt;strong&gt;runtime metrics&lt;/strong&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>16.7 The Language Server Protocol</title>
      <link>/en/part5toolchain/ch16tools/gopls/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>/en/part5toolchain/ch16tools/gopls/</guid>
      <description>&lt;h1 id=&#34;167-the-language-server-protocol&#34;&gt;16.7 The Language Server Protocol&lt;/h1&gt;&#xA;&lt;p&gt;Auto-completion, jump-to-definition, live error reporting, refactoring: in modern editors these features, on the Go side, are provided by &lt;strong&gt;&lt;code&gt;gopls&lt;/code&gt;&lt;/strong&gt; (the Go language server, pronounced &amp;ldquo;go please&amp;rdquo;). Behind it stands the &lt;strong&gt;Language Server Protocol&lt;/strong&gt; (LSP). This section makes three things clear: the combinatorial explosion that LSP untangles, how gopls builds on the reusable libraries of the compiler frontend, and why it deserves to be called the culmination of the Go toolchain&amp;rsquo;s design philosophy.&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
