5.4 效能最佳化與未來展望#
效能分析的第一定律#
\[ \text{先測量,再最佳化} \quad(\text{Knuth: premature optimization is the root of all evil}) \]
效能工作必須以量測開始,否則你在最佳化錯的東西。關鍵指標:
- 後端:吞吐量(RPS)、延遲分布(P50/P95/P99,均值會說謊)、錯誤率
- 前端:TTI(可互動時間)、列表滾動 FPS、bundle 大小
\[ \text{可用性感受由尾延遲決定}: \text{P99} \gg \text{mean} \quad\text{(長尾才是痛點)} \]
後端最佳化:熱點與手段#
1. N+1 查詢問題#
// 反模式:每篇文章再查一次作者 → 1 + N 次查詢
for post in posts {
post.author = repo::find_user(&pool, post.user_id).await?;
}
// 正解:一次 JOIN 或 WHERE IN
let rows = sqlx::query_as!(PostWithAuthor,
"SELECT p.*, u.name AS author_name
FROM posts p JOIN users u ON u.id = p.user_id
WHERE p.id = ANY($1)", &ids)
.fetch_all(&pool).await?;
\[ T_{N+1} = (N+1) \cdot RTT \quad\Rightarrow\quad T_{join} = 1 \cdot RTT \]
2. 快取的層次與一致性代價#
| 層 | 工具 | 一致性問題 |
|---|---|---|
| 記憶體 | moka(本地 LRU) | 多實例各自為政 |
| 共享 | Redis | 需失效策略 |
| HTTP | Cache-Control / ETag | 客戶端快取 |
快取的唯一難題是失效(電腦科學兩大難題之一)。實務法則:快取「不變式資料」(以 ID + 版本為 key),寫入時主動失效;絕不快取會被併發修改的聚合。
3. 資料庫#
- 索引要跟著查詢模式走:
EXPLAIN ANALYZE是唯一真相 - 分頁用 cursor(
WHERE created_at < $1)而非OFFSET(OFFSET 是 \(O(n)\) 掃描) - 大量寫入用批次(單一
INSERT ... VALUES (...), (...))
4. 併發細節(回顧 2.3)#
- CPU 密集 →
tokio::task::spawn_blocking或 rayon,避免餓死 worker - 批次 I/O →
try_join_all(序列 → 併發)
前端最佳化#
渲染最小化#
// 只在 done 變更時重渲染單列
const TodoItem = React.memo(function TodoItem({ todo, onToggle }) {
return /* ... */;
}, (a, b) => a.done === b.done && a.title === b.title);
列表虛擬化#
FlatList 已內建視窗化(windowing):只渲染可視區 ± 緩衝區的列。
\[ \text{渲染成本}: O(n) \Rightarrow O(\text{視窗高度}) \]
資源與啟動#
- Hermes 引擎(Expo 預設):AOT 位元碼,啟動更快
- 圖片:
expo-image快取 + 適當尺寸 + WebP - bundle 分析:把重依賴(圖表庫等)延遲載入
全鏈路的理論上限#
Amdahl 定律給出最佳化的天花板:
\[ S = \frac{1}{(1-p) + \dfrac{p}{s}} \]
其中 \(p\) 是可加速比例、 \(s\) 是加速倍數。序列部分(1-p)決定極限 —— 全鏈路中,最難縮短的是網路 RTT 與人類反應時間。所以:CDN 把靜態資源推近、API 就近部署、樂觀更新把感知延遲歸零(4.4),都是在壓縮這個序列項。
未來展望#
技術演化方向#
timeline
title 趨勢
2023 : React Server Components 穩定化\nRust WASM 進入瀏覽器
2024 : New Architecture 預設(Expo)\nAI 輔助編碼普及
2025+ : 型別即契約的全棧框架常態化\n邊緣運算部署(Rust 的優勢擴大)值得關注的連接點:
- Rust → WebAssembly:同一套 Rust 驗證/解析邏輯可編譯進前端,兩端共用程式碼(Leptos/Yew 甚至是「React 思想 + Rust」的全面嘗試)
- Server Components:把「伺服器渲染 + 串流」與 React 模型融合,前端資料抓取進一步內化
- AI 輔助:當型別即規格,LLM 生成程式碼的正確性可被編譯器驗證 —— 型別系統成為人機協作的契約介面
結語:本書的統一主題#
回顧全書,所有技術選擇都服務於同一條因果鏈:
flowchart LR
A[錯誤越早發現越便宜] --> B[型別即規格]
B --> C[編譯器作為驗證者]
C --> D[所有權/ADT/Trait\nSQLx 檢查/OpenAPI 管道]
D --> E[可靠的全端系統]
F[抽象與控制的平衡] --> G[零成本抽象]
G --> H[Axum 效能 + React 生產力]
H --> E技術會過時,這條因果鏈不會。換框架時,問的問題依然是:它把哪類錯誤往左移了?它的抽象成本是什麼? 這就是理論給你的、超越任何單一技術的判斷力。
習題#
- 對你的 Todo 應用做延遲量測,找出 P99 尾延遲的來源並修復。
- 用 Amdahl 定律估算:若網路 RTT 占總延遲 60%,其他部分快 10 倍,總加速比?
- 選一個未出現在本書的技術(如 GraphQL、tRPC),用本書的因果鏈框架分析它解決什麼問題、代價是什麼。