<?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>Improvement on Tarragon</title><link>https://tarrragon.github.io/blog/tags/improvement/</link><description>Recent content in Improvement on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Tue, 12 May 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/improvement/index.xml" rel="self" type="application/rss+xml"/><item><title>9.9 Performance Improvement Loop</title><link>https://tarrragon.github.io/blog/backend/09-performance-capacity/improvement-loop/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/09-performance-capacity/improvement-loop/</guid><description>&lt;h2 id="概念定位">概念定位&lt;/h2>
&lt;p>Improvement loop 的責任是把效能優化從「事件型 hotfix」變成「持續改進的工程流程」。沒有 loop 時、效能問題靠 oncall 觸發、改了又改、改完又退化；有 loop 之後、每次 release 都通過 perf gate、退化在發布前就攔住。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/performance-regression-gate/" data-link-title="6.13 Performance Regression Gate" data-link-desc="把效能 baseline 從一次性壓測變成持續對齊的 release gate，涵蓋 baseline 設定、判讀方法、variance 控制與退化定位">06.13 perf regression gate&lt;/a> 的關係：06.13 是 release gate 的一個環節、9.9 是這個 gate 背後的完整工程閉環。06.13 處理「進 gate 後怎麼判斷」、9.9 處理「進 gate 前怎麼產生比較資料」。&lt;/p>
&lt;p>本章聚焦在 &lt;em>閉環設計&lt;/em> — 怎麼建 baseline、怎麼跑 re-test、怎麼用 profile diff、怎麼整合 CI。讀完後讀者能設計一個 perf improvement workflow、不是只有 ad-hoc 壓測。&lt;/p>
&lt;h2 id="loop-五個階段">Loop 五個階段&lt;/h2>
&lt;p>完整的 improvement loop 包含五個階段、缺一不可：&lt;/p>
&lt;p>&lt;strong>1. Baseline 建立&lt;/strong>：壓測 + profile 取得「當前正常」snapshot。
&lt;strong>2. 變更 + re-test&lt;/strong>：每次 release candidate 跑壓測、跟 baseline diff。
&lt;strong>3. Profile diff&lt;/strong>：用 flame graph diff 定位退化原因。
&lt;strong>4. Fix&lt;/strong>：rollback 或修正 code path。
&lt;strong>5. Update baseline&lt;/strong>：通過後更新 baseline、進下個 cycle。&lt;/p>
&lt;p>少了 baseline → re-test 沒有比較對象、看絕對數字會錯判。
少了 profile diff → 退化定位靠猜、修錯方向。
少了 update baseline → 永遠跟 old baseline 比、退化累積看不出來。
少了 fix → 退化通過 gate、production 出事。&lt;/p>
&lt;h2 id="baseline-設計">Baseline 設計&lt;/h2>
&lt;p>Baseline 不是「歷史最佳」、是「最低可接受效能」。&lt;/p>
&lt;p>&lt;strong>設計原則&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>不只一個 baseline、按 workload model 訂多個（不同 endpoint、不同 user tier 各自 baseline）&lt;/li>
&lt;li>baseline 必須可重複：固定 seed、固定資料集、固定環境、固定壓測參數&lt;/li>
&lt;li>定期 review：硬體 / 軟體升級會讓 baseline 該往好的方向走、不更新就是裝盲&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>儲存策略&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>baseline as artifact：存進 release artifact、隨 release 帶走&lt;/li>
&lt;li>baseline as code：用 Pulumi / Terraform / dedicated config 管理、可 version control&lt;/li>
&lt;li>baseline as service：dedicated service 管 baseline、提供 query API&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Drift 監控&lt;/strong>：baseline 每月對比上月、看趨勢是否往好方向。drift 超門檻 → re-baseline 並 review 原因。&lt;/p>
&lt;h2 id="profile-diff">Profile diff&lt;/h2>
&lt;p>退化定位的關鍵工具是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/profile-diff/" data-link-title="Profile Diff" data-link-desc="對比兩次 profile（如 release candidate vs baseline）找出 hottest 變化">profile diff&lt;/a> — 對比兩次 profile 找 hottest 變化。&lt;/p></description><content:encoded><![CDATA[<h2 id="概念定位">概念定位</h2>
<p>Improvement loop 的責任是把效能優化從「事件型 hotfix」變成「持續改進的工程流程」。沒有 loop 時、效能問題靠 oncall 觸發、改了又改、改完又退化；有 loop 之後、每次 release 都通過 perf gate、退化在發布前就攔住。</p>
<p>跟 <a href="/blog/backend/06-reliability/performance-regression-gate/" data-link-title="6.13 Performance Regression Gate" data-link-desc="把效能 baseline 從一次性壓測變成持續對齊的 release gate，涵蓋 baseline 設定、判讀方法、variance 控制與退化定位">06.13 perf regression gate</a> 的關係：06.13 是 release gate 的一個環節、9.9 是這個 gate 背後的完整工程閉環。06.13 處理「進 gate 後怎麼判斷」、9.9 處理「進 gate 前怎麼產生比較資料」。</p>
<p>本章聚焦在 <em>閉環設計</em> — 怎麼建 baseline、怎麼跑 re-test、怎麼用 profile diff、怎麼整合 CI。讀完後讀者能設計一個 perf improvement workflow、不是只有 ad-hoc 壓測。</p>
<h2 id="loop-五個階段">Loop 五個階段</h2>
<p>完整的 improvement loop 包含五個階段、缺一不可：</p>
<p><strong>1. Baseline 建立</strong>：壓測 + profile 取得「當前正常」snapshot。
<strong>2. 變更 + re-test</strong>：每次 release candidate 跑壓測、跟 baseline diff。
<strong>3. Profile diff</strong>：用 flame graph diff 定位退化原因。
<strong>4. Fix</strong>：rollback 或修正 code path。
<strong>5. Update baseline</strong>：通過後更新 baseline、進下個 cycle。</p>
<p>少了 baseline → re-test 沒有比較對象、看絕對數字會錯判。
少了 profile diff → 退化定位靠猜、修錯方向。
少了 update baseline → 永遠跟 old baseline 比、退化累積看不出來。
少了 fix → 退化通過 gate、production 出事。</p>
<h2 id="baseline-設計">Baseline 設計</h2>
<p>Baseline 不是「歷史最佳」、是「最低可接受效能」。</p>
<p><strong>設計原則</strong>：</p>
<ul>
<li>不只一個 baseline、按 workload model 訂多個（不同 endpoint、不同 user tier 各自 baseline）</li>
<li>baseline 必須可重複：固定 seed、固定資料集、固定環境、固定壓測參數</li>
<li>定期 review：硬體 / 軟體升級會讓 baseline 該往好的方向走、不更新就是裝盲</li>
</ul>
<p><strong>儲存策略</strong>：</p>
<ul>
<li>baseline as artifact：存進 release artifact、隨 release 帶走</li>
<li>baseline as code：用 Pulumi / Terraform / dedicated config 管理、可 version control</li>
<li>baseline as service：dedicated service 管 baseline、提供 query API</li>
</ul>
<p><strong>Drift 監控</strong>：baseline 每月對比上月、看趨勢是否往好方向。drift 超門檻 → re-baseline 並 review 原因。</p>
<h2 id="profile-diff">Profile diff</h2>
<p>退化定位的關鍵工具是 <a href="/blog/backend/knowledge-cards/profile-diff/" data-link-title="Profile Diff" data-link-desc="對比兩次 profile（如 release candidate vs baseline）找出 hottest 變化">profile diff</a> — 對比兩次 profile 找 hottest 變化。</p>
<p><strong>工具實作</strong>：</p>
<ul>
<li>Brendan Gregg 的 differential flame graph：開源、需要手動 generate</li>
<li>Pyroscope diff：UI 直接對比兩個時間段</li>
<li>Datadog Continuous Profiler diff：跟 deployment marker 整合</li>
<li>Parca compare：CNCF 標準</li>
<li>AWS CodeGuru Profiler：自動偵測 CPU / memory anti-pattern</li>
</ul>
<p><strong>正確使用方法</strong>：</p>
<ul>
<li>在 <em>相同負載 + 相同硬體 + 相同 sampling rate</em> 下取兩次 profile</li>
<li>比較 <em>相對變化</em>、不是絕對 CPU%</li>
<li>看 wider stack（不只看 leaf function）找 systemic regression</li>
</ul>
<p><strong>Profile diff 結果通常需要工程師判讀</strong>：「多花 20% CPU 但 throughput 多 50%」可能是好變化、不能純自動化判斷退化是否可接受。</p>
<p>對應案例：<a href="/blog/backend/09-performance-capacity/cases/netflix-aurora-consolidation/" data-link-title="9.C23 Netflix：把關聯式 DB 統一到 Aurora、效能 &#43;75%、成本 -28%" data-link-desc="Netflix 把多套關聯式 DB 統一到 Aurora、效能提升 75%、成本下降 28%、串流數十億小時">Netflix Aurora 統一</a> — DB 層統一後 profile diff 噪音降低、退化來源更容易識別。</p>
<h2 id="regression-gate-整合-ci">Regression gate 整合 CI</h2>
<p>效能改進閉環必須整合到 CI、不能只在 release 前一次性跑。</p>
<p><strong>Multi-tier 壓測策略</strong>：</p>
<ul>
<li>每個 PR：跑 lightweight perf test（單 endpoint、5 分鐘）、合併前比 baseline</li>
<li>主分支 nightly：跑 medium perf test（多 endpoint、30 分鐘）</li>
<li>Release candidate：跑 complete perf test（完整 workload model、數小時）</li>
</ul>
<p><strong>Gate 觸發條件</strong>：</p>
<ul>
<li>p99 退化 &gt; X%（例如 10%）</li>
<li>吞吐降 &gt; Y%（例如 5%）</li>
<li>error rate 升 &gt; Z%</li>
<li>cost per request 升 &gt; W%</li>
</ul>
<p><strong>Gate 通過 / 不通過的後果</strong>：</p>
<ul>
<li>通過：自動 promote 到下個 stage（staging / canary / production）</li>
<li>不通過：block release、自動 notify owner、附 profile diff link</li>
</ul>
<p><strong>Gate 太敏感的反模式</strong>：</p>
<ul>
<li>每天 false positive、最後沒人看（alert fatigue）</li>
<li>false positive 來源：壓測環境噪音、baseline drift 未更新、業務變化</li>
<li>對策：multi-window detection（變化必須持續 N 個 sample）、配合 manual override（資深工程師判斷異常正常）</li>
</ul>
<p>對應案例：<a href="/blog/backend/06-reliability/performance-regression-gate/" data-link-title="6.13 Performance Regression Gate" data-link-desc="把效能 baseline 從一次性壓測變成持續對齊的 release gate，涵蓋 baseline 設定、判讀方法、variance 控制與退化定位">06.13 perf regression gate</a> 的實作建議。</p>
<h2 id="canary-perf-check">Canary perf check</h2>
<p><a href="/blog/backend/knowledge-cards/canary-perf-check/" data-link-title="Canary Perf Check" data-link-desc="canary release 中針對 latency / throughput 而非 error rate 的退化檢查">Canary perf check</a> 是 release 階段的另一道 perf gate。跟 regression gate（pre-release）對應、是 <em>production</em> 階段的監控。</p>
<p><strong>Canary 階段除了看 error rate、也看</strong>：</p>
<ul>
<li>latency p99 / p999（最先看到的 regression 訊號）</li>
<li>throughput（是否處理變慢）</li>
<li>resource utilization（CPU / RAM / connection 變化）</li>
<li>cost per request（是否更貴）</li>
</ul>
<p><strong>Canary 流量 vs control 流量比較</strong>：</p>
<ul>
<li>同樣流量同樣時段、不同版本的差才有意義</li>
<li>不能拿 canary 跟 historical baseline 比（外部變數太多）</li>
<li>abort condition：canary p99 比 control 退化 &gt; X%</li>
</ul>
<p><strong>漸進放大策略</strong>：1% → 5% → 25% → 50% → 100%、每階段觀察足夠時間（至少 15 分鐘看 long-tail）。</p>
<p>對應案例：<a href="/blog/backend/09-performance-capacity/cases/aws-prime-day-extreme-scale-2025/" data-link-title="9.C1 AWS Prime Day 2025：可預期極端峰值的 dogfood" data-link-desc="Amazon 自家服務在 Prime Day 2025 的峰值數字 — 一年一次可預期峰值的容量設計參考">Prime Day FIS 8x chaos</a> — canary 模式跟 chaos test 並行、確保新版本在故障場景也撐得住。</p>
<h2 id="pre-release-改進迴圈頻率">Pre-release 改進迴圈頻率</h2>
<p>不同層級的 review 在不同節奏：</p>
<ul>
<li><strong>每日 PR 級 perf check</strong>：lightweight、單 endpoint、5 分鐘</li>
<li><strong>每週 release candidate 完整壓測</strong>：完整 workload model、數小時</li>
<li><strong>每月 baseline review + drift 評估</strong>：對比歷史趨勢、決定是否 re-baseline</li>
<li><strong>每季容量地圖 review</strong>：跟 <a href="/blog/backend/09-performance-capacity/capacity-planning/" data-link-title="9.6 容量規劃模型" data-link-desc="peak forecast、headroom budget、growth curve、autoscaling sizing">9.6 容量規劃模型</a> 連動</li>
</ul>
<p>頻率不夠 → 退化累積看不到；頻率太高 → 工程資源吃緊。按團隊規模跟 release 節奏調整。</p>
<h2 id="退化的常見來源">退化的常見來源</h2>
<p>知道退化怎麼來、才能設計對應的 detection：</p>
<ul>
<li><strong>新功能引入 N+1 query</strong>：ORM lazy loading、loop 內 query。看 DB call count 變化</li>
<li><strong>ORM 沒下 index、cache miss 飆升</strong>：看 slow query 跟 cache hit rate</li>
<li><strong>第三方 library upgrade 帶來 overhead</strong>：新版本可能多了 telemetry / validation。看 profile diff</li>
<li><strong>GC tuning 變動</strong>：JVM / Go GC config 調整造成 pause time 變化。看 p999</li>
<li><strong>container resource limit 變動</strong>：Kubernetes limit 改、限制更嚴造成 throttling。看 CPU throttling event</li>
</ul>
<h2 id="反模式">反模式</h2>
<ul>
<li><strong>只在 release 前一次性壓測</strong>：退化已累積數月、找不出原因</li>
<li><strong>baseline 不更新</strong>：永遠跟舊版本比、低估目前狀態</li>
<li><strong>改了又改、改完忘記更新 baseline</strong>：下次 release 又跟過時 baseline 比、迴圈失效</li>
<li><strong>缺 profile diff、退化原因靠猜</strong>：修錯方向、退化還在</li>
<li><strong>gate 訊號跟業務無關</strong>：技術指標退化但業務 metric 沒事、被當 false positive</li>
</ul>
<h2 id="案例對照">案例對照</h2>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>教學重點</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/netflix-aurora-consolidation/" data-link-title="9.C23 Netflix：把關聯式 DB 統一到 Aurora、效能 &#43;75%、成本 -28%" data-link-desc="Netflix 把多套關聯式 DB 統一到 Aurora、效能提升 75%、成本下降 28%、串流數十億小時">9.C23 Netflix</a></td>
          <td>統一 DB 後 profile 變單純</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/zomato-tidb-to-dynamodb-migration/" data-link-title="9.C20 Zomato：從 TiDB 遷移到 DynamoDB、吞吐 4 倍、延遲降 90%、成本減 50%" data-link-desc="Zomato 帳單系統從 TiDB 遷移到 DynamoDB、吞吐 2K→8K RPM、延遲降 90%、成本減 50%">9.C20 Zomato</a></td>
          <td>遷移後重新做 baseline</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/09-performance-capacity/cases/aws-prime-day-extreme-scale-2025/" data-link-title="9.C1 AWS Prime Day 2025：可預期極端峰值的 dogfood" data-link-desc="Amazon 自家服務在 Prime Day 2025 的峰值數字 — 一年一次可預期峰值的容量設計參考">9.C1 Prime Day FIS 8x</a></td>
          <td>持續改進的混沌 + 壓測迴圈</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/09-performance-capacity/saturation-discovery/" data-link-title="9.4 Saturation Discovery" data-link-desc="找出 throughput plateau 與 latency knee 的方法">9.4 Saturation Discovery</a> / <a href="/blog/backend/09-performance-capacity/bottleneck-localization/" data-link-title="9.5 瓶頸定位流程" data-link-desc="從 app 到 DB / cache / broker / 第三方 quota 的逐層瓶頸定位">9.5 瓶頸定位</a></li>
<li>下游：<a href="/blog/backend/09-performance-capacity/production-validation/" data-link-title="9.10 Production-Side 驗證" data-link-desc="shadow traffic、dark launch、canary、production-like load test">9.10 Production-Side 驗證</a></li>
<li>跨模組：<a href="/blog/backend/06-reliability/performance-regression-gate/" data-link-title="6.13 Performance Regression Gate" data-link-desc="把效能 baseline 從一次性壓測變成持續對齊的 release gate，涵蓋 baseline 設定、判讀方法、variance 控制與退化定位">06.13 perf regression gate</a> / <a href="/blog/backend/06-reliability/release-gate/" data-link-title="6.8 Release Gate 與變更節奏" data-link-desc="把驗證、migration、相容性納入放行判準">06.8 release gate</a></li>
</ul>
<h2 id="既建知識卡片">既建知識卡片</h2>
<ul>
<li><a href="/blog/backend/knowledge-cards/profile-diff/" data-link-title="Profile Diff" data-link-desc="對比兩次 profile（如 release candidate vs baseline）找出 hottest 變化">Profile Diff</a></li>
<li><a href="/blog/backend/knowledge-cards/continuous-profiling/" data-link-title="Continuous Profiling" data-link-desc="在 production 持續取得低 overhead profile 的觀察方法">Continuous Profiling</a></li>
<li><a href="/blog/backend/knowledge-cards/canary-perf-check/" data-link-title="Canary Perf Check" data-link-desc="canary release 中針對 latency / throughput 而非 error rate 的退化檢查">Canary Perf Check</a></li>
</ul>
]]></content:encoded></item></channel></rss>