<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Profile on 山高月小</title><link>https://blog.dart.xin/tags/profile/</link><description>Recent content in Profile on 山高月小</description><generator>Hugo</generator><language>zh-cn</language><copyright>zwdart</copyright><lastBuildDate>Thu, 05 Nov 2026 11:35:50 +0800</lastBuildDate><atom:link href="https://blog.dart.xin/tags/profile/index.xml" rel="self" type="application/rss+xml"/><item><title>Golang Profile</title><link>https://blog.dart.xin/golang/go111-profile/</link><pubDate>Thu, 05 Nov 2026 11:35:50 +0800</pubDate><guid>https://blog.dart.xin/golang/go111-profile/</guid><description>&lt;p&gt;Go 的 &lt;strong&gt;profile&lt;/strong&gt; 是一套内置于 runtime 的性能诊断机制，它通过&lt;strong&gt;采样或事件记录&lt;/strong&gt;的方式，持续收集程序运行时的 CPU 使用、内存分配、Goroutine 状态、锁竞争等数据，最终生成一个可分析的数据文件（&lt;code&gt;.prof&lt;/code&gt;）。&lt;code&gt;go tool pprof&lt;/code&gt; 则是解读这些数据的官方工具，能将原始数据转化为调用图、火焰图或源码级别的热点标注，帮你定位性能瓶颈。&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="-profile-的核心类型按症状选择工具"&gt;📊 Profile 的核心类型：按“症状”选择工具&lt;/h3&gt;
&lt;p&gt;每种 Profile 回答不同的问题，选错类型会浪费大量调查时间。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: left"&gt;Profile 类型&lt;/th&gt;
&lt;th style="text-align: left"&gt;采集标志 / HTTP 端点&lt;/th&gt;
&lt;th style="text-align: left"&gt;核心用途&lt;/th&gt;
&lt;th style="text-align: left"&gt;关键说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: left"&gt;&lt;strong&gt;CPU&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left"&gt;&lt;code&gt;-cpuprofile&lt;/code&gt; 或 &lt;code&gt;/debug/pprof/profile?seconds=30&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: left"&gt;高 CPU 占用、函数执行慢&lt;/td&gt;
&lt;td style="text-align: left"&gt;以 &lt;strong&gt;100Hz&lt;/strong&gt; 采样&lt;strong&gt;在 CPU 上&lt;/strong&gt;运行的函数；&lt;strong&gt;无法捕获&lt;/strong&gt; I/O、Sleep 等 Off-CPU 时间&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left"&gt;&lt;strong&gt;Heap (内存)&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left"&gt;&lt;code&gt;-memprofile&lt;/code&gt; 或 &lt;code&gt;/debug/pprof/heap&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: left"&gt;GC 压力大、内存泄漏&lt;/td&gt;
&lt;td style="text-align: left"&gt;有四种视角：&lt;code&gt;alloc_objects&lt;/code&gt;（分配次数）、&lt;code&gt;alloc_space&lt;/code&gt;（分配字节数）、&lt;code&gt;inuse_space&lt;/code&gt;（当前存活字节）、&lt;code&gt;inuse_objects&lt;/code&gt;（当前存活对象数）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left"&gt;&lt;strong&gt;Goroutine&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left"&gt;&lt;code&gt;/debug/pprof/goroutine&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: left"&gt;Goroutine 泄漏、阻塞堆积&lt;/td&gt;
&lt;td style="text-align: left"&gt;对所有 Goroutine 的调用栈进行快照；查找大量 Goroutine 堆积在&lt;strong&gt;同一调用点&lt;/strong&gt;的情况&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left"&gt;&lt;strong&gt;Mutex&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left"&gt;&lt;code&gt;/debug/pprof/mutex&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: left"&gt;锁竞争激烈&lt;/td&gt;
&lt;td style="text-align: left"&gt;记录 Goroutine 等待获取锁的&lt;strong&gt;累计时间&lt;/strong&gt;；默认关闭，需 &lt;code&gt;runtime.SetMutexProfileFraction()&lt;/code&gt; 开启&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left"&gt;&lt;strong&gt;Block&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left"&gt;&lt;code&gt;/debug/pprof/block&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: left"&gt;Channel/Mutex/Select 阻塞&lt;/td&gt;
&lt;td style="text-align: left"&gt;记录 Goroutine 在同步原语上的&lt;strong&gt;累计阻塞时间&lt;/strong&gt;；默认关闭，需 &lt;code&gt;runtime.SetBlockProfileRate()&lt;/code&gt; 开启&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left"&gt;&lt;strong&gt;Threadcreate&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left"&gt;&lt;code&gt;/debug/pprof/threadcreate&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: left"&gt;OS 线程过度创建&lt;/td&gt;
&lt;td style="text-align: left"&gt;显示创建新 OS 线程的调用栈，通常由 cgo 或阻塞系统调用导致&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h3 id="-三种采集方式按场景选择入口"&gt;🛠️ 三种采集方式：按“场景”选择入口&lt;/h3&gt;
&lt;h4 id="-代码植入式runtimepprof适用于独立程序或精确控制"&gt;💻 代码植入式（&lt;code&gt;runtime/pprof&lt;/code&gt;）：适用于独立程序或精确控制&lt;/h4&gt;
&lt;p&gt;在代码中手动启动和停止，适合命令行工具、离线分析或需要精确控制采集时机的场景。&lt;/p&gt;</description><content:encoded><![CDATA[<p>Go 的 <strong>profile</strong> 是一套内置于 runtime 的性能诊断机制，它通过<strong>采样或事件记录</strong>的方式，持续收集程序运行时的 CPU 使用、内存分配、Goroutine 状态、锁竞争等数据，最终生成一个可分析的数据文件（<code>.prof</code>）。<code>go tool pprof</code> 则是解读这些数据的官方工具，能将原始数据转化为调用图、火焰图或源码级别的热点标注，帮你定位性能瓶颈。</p>
<hr>
<h3 id="-profile-的核心类型按症状选择工具">📊 Profile 的核心类型：按“症状”选择工具</h3>
<p>每种 Profile 回答不同的问题，选错类型会浪费大量调查时间。</p>
<table>
	<thead>
			<tr>
					<th style="text-align: left">Profile 类型</th>
					<th style="text-align: left">采集标志 / HTTP 端点</th>
					<th style="text-align: left">核心用途</th>
					<th style="text-align: left">关键说明</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td style="text-align: left"><strong>CPU</strong></td>
					<td style="text-align: left"><code>-cpuprofile</code> 或 <code>/debug/pprof/profile?seconds=30</code></td>
					<td style="text-align: left">高 CPU 占用、函数执行慢</td>
					<td style="text-align: left">以 <strong>100Hz</strong> 采样<strong>在 CPU 上</strong>运行的函数；<strong>无法捕获</strong> I/O、Sleep 等 Off-CPU 时间</td>
			</tr>
			<tr>
					<td style="text-align: left"><strong>Heap (内存)</strong></td>
					<td style="text-align: left"><code>-memprofile</code> 或 <code>/debug/pprof/heap</code></td>
					<td style="text-align: left">GC 压力大、内存泄漏</td>
					<td style="text-align: left">有四种视角：<code>alloc_objects</code>（分配次数）、<code>alloc_space</code>（分配字节数）、<code>inuse_space</code>（当前存活字节）、<code>inuse_objects</code>（当前存活对象数）</td>
			</tr>
			<tr>
					<td style="text-align: left"><strong>Goroutine</strong></td>
					<td style="text-align: left"><code>/debug/pprof/goroutine</code></td>
					<td style="text-align: left">Goroutine 泄漏、阻塞堆积</td>
					<td style="text-align: left">对所有 Goroutine 的调用栈进行快照；查找大量 Goroutine 堆积在<strong>同一调用点</strong>的情况</td>
			</tr>
			<tr>
					<td style="text-align: left"><strong>Mutex</strong></td>
					<td style="text-align: left"><code>/debug/pprof/mutex</code></td>
					<td style="text-align: left">锁竞争激烈</td>
					<td style="text-align: left">记录 Goroutine 等待获取锁的<strong>累计时间</strong>；默认关闭，需 <code>runtime.SetMutexProfileFraction()</code> 开启</td>
			</tr>
			<tr>
					<td style="text-align: left"><strong>Block</strong></td>
					<td style="text-align: left"><code>/debug/pprof/block</code></td>
					<td style="text-align: left">Channel/Mutex/Select 阻塞</td>
					<td style="text-align: left">记录 Goroutine 在同步原语上的<strong>累计阻塞时间</strong>；默认关闭，需 <code>runtime.SetBlockProfileRate()</code> 开启</td>
			</tr>
			<tr>
					<td style="text-align: left"><strong>Threadcreate</strong></td>
					<td style="text-align: left"><code>/debug/pprof/threadcreate</code></td>
					<td style="text-align: left">OS 线程过度创建</td>
					<td style="text-align: left">显示创建新 OS 线程的调用栈，通常由 cgo 或阻塞系统调用导致</td>
			</tr>
	</tbody>
</table>
<hr>
<h3 id="-三种采集方式按场景选择入口">🛠️ 三种采集方式：按“场景”选择入口</h3>
<h4 id="-代码植入式runtimepprof适用于独立程序或精确控制">💻 代码植入式（<code>runtime/pprof</code>）：适用于独立程序或精确控制</h4>
<p>在代码中手动启动和停止，适合命令行工具、离线分析或需要精确控制采集时机的场景。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;os&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;runtime/pprof&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;time&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// 启动 CPU Profile</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">f</span><span class="p">,</span><span class="w"> </span><span class="nx">_</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">os</span><span class="p">.</span><span class="nf">Create</span><span class="p">(</span><span class="s">&#34;cpu.prof&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">pprof</span><span class="p">.</span><span class="nf">StartCPUProfile</span><span class="p">(</span><span class="nx">f</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">defer</span><span class="w"> </span><span class="nx">pprof</span><span class="p">.</span><span class="nf">StopCPUProfile</span><span class="p">()</span><span class="w"> </span><span class="c1">// 确保程序退出前停止并写入文件</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// 模拟耗时工作</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">time</span><span class="p">.</span><span class="nf">Sleep</span><span class="p">(</span><span class="mi">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">time</span><span class="p">.</span><span class="nx">Second</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nf">busyWork</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// 在特定时间点采集 Heap Profile</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">hf</span><span class="p">,</span><span class="w"> </span><span class="nx">_</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">os</span><span class="p">.</span><span class="nf">Create</span><span class="p">(</span><span class="s">&#34;heap.prof&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">pprof</span><span class="p">.</span><span class="nf">WriteHeapProfile</span><span class="p">(</span><span class="nx">hf</span><span class="p">)</span><span class="w"> </span><span class="c1">// 快照当前堆状态</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">hf</span><span class="p">.</span><span class="nf">Close</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">busyWork</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">for</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="p">&lt;</span><span class="w"> </span><span class="mf">1e8</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="o">++</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">_</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">i</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><p><strong>运行与分析</strong>：<code>go run main.go</code> 后会生成 <code>cpu.prof</code> 和 <code>heap.prof</code>，然后执行 <code>go tool pprof cpu.prof</code> 进入交互界面。</p>
<h4 id="-http-端点式nethttppprof适用于在线服务最常用">🌐 HTTP 端点式（<code>net/http/pprof</code>）：适用于在线服务（最常用）</h4>
<p>为运行中的服务开一个“诊断端口”，无需重启即可实时采集，是生产环境排查问题的首选。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;log&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;net/http&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">_</span><span class="w"> </span><span class="s">&#34;net/http/pprof&#34;</span><span class="w"> </span><span class="c1">// 匿名导入，自动注册 /debug/pprof/ 路由</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="s">&#34;time&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// 在独立端口启动 pprof 服务，避免与业务端口冲突</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">go</span><span class="w"> </span><span class="kd">func</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">log</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">http</span><span class="p">.</span><span class="nf">ListenAndServe</span><span class="p">(</span><span class="s">&#34;:6060&#34;</span><span class="p">,</span><span class="w"> </span><span class="kc">nil</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="c1">// 业务逻辑（模拟）</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">for</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nx">time</span><span class="p">.</span><span class="nf">Sleep</span><span class="p">(</span><span class="nx">time</span><span class="p">.</span><span class="nx">Second</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><p><strong>运行与分析</strong>：</p>
<ol>
<li><code>go run main.go</code> 启动服务。</li>
<li>新终端执行采集：
<ul>
<li><strong>CPU</strong>：<code>go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30</code>（采集 30 秒）</li>
<li><strong>Heap</strong>：<code>go tool pprof http://localhost:6060/debug/pprof/heap</code></li>
<li><strong>Goroutine</strong>：<code>go tool pprof http://localhost:6060/debug/pprof/goroutine</code></li>
</ul>
</li>
</ol>
<h4 id="-基准测试式go-test适用于微基准和优化对比">🧪 基准测试式（<code>go test</code>）：适用于微基准和优化对比</h4>
<p>在基准测试中直接采集，无需编写额外代码，适合对比优化前后的差异。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="c1">// 在 _test.go 文件中</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">BenchmarkBusyWork</span><span class="p">(</span><span class="nx">b</span><span class="w"> </span><span class="o">*</span><span class="nx">testing</span><span class="p">.</span><span class="nx">B</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">for</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="p">&lt;</span><span class="w"> </span><span class="nx">b</span><span class="p">.</span><span class="nx">N</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="o">++</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="nf">busyWork</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><p><strong>运行与分析</strong>：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">go <span class="nb">test</span> -bench<span class="o">=</span>BenchmarkBusyWork -cpuprofile<span class="o">=</span>cpu.prof -memprofile<span class="o">=</span>mem.prof .
</span></span><span class="line"><span class="cl">go tool pprof -http<span class="o">=</span>:8080 cpu.prof   <span class="c1"># 直接打开 Web UI 查看</span>
</span></span></code></pre></td></tr></table>
</div>
</div><hr>
<h3 id="-分析工具从数据到洞察">🔍 分析工具：从数据到洞察</h3>
<h4 id="-交互式-cligo-tool-pprof">💻 交互式 CLI：<code>go tool pprof</code></h4>
<p>进入交互模式后，核心命令如下：</p>
<table>
	<thead>
			<tr>
					<th style="text-align: left">命令</th>
					<th style="text-align: left">作用</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td style="text-align: left"><strong><code>top</code></strong></td>
					<td style="text-align: left">按<strong>自身耗时</strong>排名，首选命令</td>
			</tr>
			<tr>
					<td style="text-align: left"><strong><code>top -cum</code></strong></td>
					<td style="text-align: left">按<strong>累积耗时</strong>排名（包含子调用）</td>
			</tr>
			<tr>
					<td style="text-align: left"><strong><code>list funcName</code></strong></td>
					<td style="text-align: left">展示函数的<strong>源码级</strong>耗时标注</td>
			</tr>
			<tr>
					<td style="text-align: left"><strong><code>web</code></strong></td>
					<td style="text-align: left">生成<strong>调用图</strong>（需 Graphviz）</td>
			</tr>
			<tr>
					<td style="text-align: left"><strong><code>peek funcName</code></strong></td>
					<td style="text-align: left">查看函数的调用者和被调用者</td>
			</tr>
	</tbody>
</table>
<h4 id="-web-ui-http-标志推荐">🌐 Web UI：<code>-http</code> 标志（推荐）</h4>
<p><code>go tool pprof -http=:8080 cpu.prof</code> 会在浏览器打开交互式界面，核心视图是<strong>火焰图（Flame Graph）</strong>。</p>
<p><strong>火焰图读法</strong>：</p>
<ul>
<li><strong>纵轴</strong>：调用栈深度，越往下是越底层的调用。</li>
<li><strong>横轴</strong>：代表耗时占比，<strong>越宽表示该函数消耗的时间越多</strong>。</li>
<li><strong>交互</strong>：鼠标悬浮可查看详细数据，点击可放大该分支。</li>
</ul>
<h4 id="-火焰图生成工具go-torch经典工具">🔥 火焰图生成工具：<code>go-torch</code>（经典工具）</h4>
<p>Uber 开源的 <code>go-torch</code> 可直接从运行中的服务或 <code>.prof</code> 文件生成交互式 SVG 火焰图。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 安装</span>
</span></span><span class="line"><span class="cl">go install github.com/uber/go-torch@latest
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 从运行中的服务生成（采集 30 秒）</span>
</span></span><span class="line"><span class="cl">go-torch -u http://localhost:6060 -t <span class="m">30</span> -f profile.svg
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 从已有的 .prof 文件生成</span>
</span></span><span class="line"><span class="cl">go-torch --binaryinput cpu.prof --binaryname &lt;你的二进制文件名&gt;
</span></span></code></pre></td></tr></table>
</div>
</div><p>生成的 <code>profile.svg</code> 可用浏览器打开，交互体验与 <code>pprof -http</code> 的火焰图类似。</p>
<hr>
<h3 id="-总结">💎 总结</h3>
<p>Go 的 Profile 体系可以概括为 <strong>“三类入口、七种视图、一个工具”</strong>：</p>
<ul>
<li><strong>三类入口</strong>：代码植入（<code>runtime/pprof</code>）、HTTP 端点（<code>net/http/pprof</code>）、基准测试（<code>go test</code>）。</li>
<li><strong>七种视图</strong>：CPU、Heap（四种子视图）、Goroutine、Mutex、Block、Threadcreate，<strong>按症状选择</strong>。</li>
<li><strong>一个工具</strong>：<code>go tool pprof</code>，通过 CLI 或 Web UI（火焰图）将数据转化为可操作的优化线索。</li>
</ul>
<p><strong>核心原则</strong>：<strong>先匹配症状到 Profile 类型，再选择采集入口，最后用火焰图定位热点</strong>。Mutex 和 Block Profile 默认关闭，需要时务必先通过 <code>runtime</code> 包开启。</p>
]]></content:encoded></item></channel></rss>