Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Systems Performance 2/e - 實用工具完整指南

📚 書籍簡介

《Systems Performance: Enterprise and the Cloud, 2nd Edition》(2020) 是 Brendan Gregg 的經典系統性能分析著作,涵蓋了現代系統性能優化的完整方法論和工具集。

🎯 性能分析方法論

USE 方法論

  • Utilization (使用率): 資源用了多少?
  • Saturation (飽和度): 有多少在排隊等待?
  • Errors (錯誤): 有錯誤發生嗎?

60秒快速診斷法

# 60秒內快速瞭解系統狀態
uptime                  # 系統負載
dmesg | tail           # 系統訊息
vmstat 1               # 虛擬記憶體統計
mpstat -P ALL 1        # CPU統計
pidstat 1              # 進程統計
iostat -xz 1           # I/O統計
free -m                # 記憶體使用
sar -n DEV 1           # 網路設備統計
sar -n TCP,ETCP 1      # TCP統計
top                    # 進程總覽

🔧 系統層級工具

1. 基礎觀察工具

vmstat - 虛擬記憶體統計

vmstat 1
# 輸出說明:
# r: 等待CPU的進程數(runnable)
# b: 被阻塞的進程數(blocked)
# free: 空閒記憶體
# si/so: swap in/out

💡 白話說明:就像看汽車儀錶板,一眼就知道系統忙不忙

iostat - I/O 統計

iostat -x 1
# 關鍵指標:
# %util: 磁碟忙碌程度(100%表示滿載)
# await: 平均等待時間
# r/s, w/s: 每秒讀寫次數

💡 白話說明:監控硬碟的"心跳",看是否有I/O瓶頸

top/htop - 進程監控

htop
# 互動式操作:
# F6: 排序
# F4: 過濾
# F9: 殺進程

💡 白話說明:Linux版的任務管理器,即時查看資源消耗

2. 進階診斷工具

perf - Linux 性能分析框架

# CPU採樣分析
perf record -F 99 -g ./your_program
perf report

# 即時統計
perf stat ./your_program

# 系統調用追蹤
perf trace ./your_program

💡 白話說明:像X光機,能看到程式內部的執行熱點

strace/ltrace - 系統調用追蹤

# 追蹤系統調用
strace -c ./program    # 統計模式
strace -T ./program    # 顯示時間

# 追蹤函式庫調用
ltrace ./program

💡 白話說明:偷看程式和系統的"對話記錄"

3. BPF 新世代工具

bpftrace - 動態追蹤語言

# 追蹤檔案開啟
bpftrace -e 'tracepoint:syscalls:sys_enter_open { 
    printf("%s opened %s\n", comm, str(args->filename)); 
}'

# 追蹤進程創建
bpftrace -e 'tracepoint:sched:sched_process_fork { 
    printf("PID %d created PID %d\n", pid, args->child_pid); 
}'

# 分析系統調用延遲
bpftrace -e 'tracepoint:raw_syscalls:sys_enter { 
    @start[tid] = nsecs; 
} 
tracepoint:raw_syscalls:sys_exit /@start[tid]/ { 
    @ns = hist(nsecs - @start[tid]); delete(@start[tid]); 
}'

💡 白話說明:在系統裡裝"探針",想監控什麼就監控什麼

bcc 工具集

# TCP 連線生命週期
tcplife

# 檔案 I/O 延遲分析
ext4slower

# 執行緒阻塞分析
offcputime -p PID

# 記憶體分配追蹤
memleak -p PID

🔥 火焰圖 (Flame Graphs)

CPU 火焰圖

# 1. 收集數據(30秒)
perf record -F 99 -ag -- sleep 30

# 2. 生成火焰圖
perf script | stackcollapse-perf.pl | flamegraph.pl > cpu-flame.svg

# 3. 針對特定進程
perf record -F 99 -p PID -g -- sleep 30

Off-CPU 火焰圖

# 分析程式在等待什麼
bpftrace -e 'kprobe:finish_task_switch { 
    @[kstack, ustack, comm] = count(); 
}' > out.stacks
cat out.stacks | flamegraph.pl > offcpu-flame.svg

💡 白話說明:火焰圖把執行時間視覺化,寬度代表時間佔比,一眼看出瓶頸

💻 C++ 性能分析工具

1. Valgrind 套件

# 記憶體洩漏檢測
valgrind --leak-check=full --show-leak-kinds=all ./cpp_program

# CPU 分析(callgrind)
valgrind --tool=callgrind ./cpp_program
kcachegrind callgrind.out.*  # 視覺化檢視

# 快取分析
valgrind --tool=cachegrind ./cpp_program

2. Google Performance Tools (gperftools)

// 在程式碼中使用
#include <gperftools/profiler.h>

int main() {
    ProfilerStart("cpu_profile.prof");
    // 你的程式碼
    ProfilerStop();
}
# 編譯連結
g++ -o program program.cpp -lprofiler

# 分析結果
pprof --text ./program cpu_profile.prof
pprof --pdf ./program cpu_profile.prof > profile.pdf

3. AddressSanitizer (ASan)

# 編譯時啟用
g++ -fsanitize=address -g -O1 program.cpp -o program

# 執行時會自動檢測:
# - 緩衝區溢出
# - Use-after-free
# - 記憶體洩漏

4. C++ 專用 perf 分析

# 編譯優化但保留符號
g++ -O2 -g -fno-omit-frame-pointer program.cpp

# 收集性能數據
perf record -g ./program
perf report

# 產生註解的原始碼
perf annotate --stdio

🦀 Rust 性能分析工具

1. Cargo 內建工具

# 編譯優化版本
cargo build --release

# 執行基準測試
cargo bench

# 使用 flamegraph
cargo install flamegraph
cargo flamegraph --bin your_program

2. Rust 專用分析工具

# Cargo.toml 加入依賴
[profile.release]
debug = true  # 保留除錯符號

[dev-dependencies]
criterion = "0.5"  # 基準測試框架
#![allow(unused)]
fn main() {
// 使用 criterion 基準測試
use criterion::{black_box, criterion_group, criterion_main, Criterion};

fn fibonacci(n: u64) -> u64 {
    match n {
        0 => 1,
        1 => 1,
        n => fibonacci(n-1) + fibonacci(n-2),
    }
}

fn bench_fibonacci(c: &mut Criterion) {
    c.bench_function("fib 20", |b| b.iter(|| fibonacci(black_box(20))));
}

criterion_group!(benches, bench_fibonacci);
criterion_main!(benches);
}

3. Tokio Console (非同步程式)

# 用於非同步 Rust 程式
[dependencies]
console-subscriber = "0.2"
tokio = { version = "1", features = ["full", "tracing"] }
#[tokio::main]
async fn main() {
    console_subscriber::init();
    // 你的非同步程式碼
}
# 安裝並執行 console
cargo install --locked tokio-console
tokio-console

4. Miri (記憶體安全檢查)

# 安裝 Miri
rustup +nightly component add miri

# 執行記憶體安全檢查
cargo +nightly miri run
cargo +nightly miri test

📊 實戰場景範例

場景 1:C++ 程式記憶體洩漏

# 快速診斷流程
1. valgrind --leak-check=full ./program
2. 如果太慢,使用 AddressSanitizer:
   g++ -fsanitize=address program.cpp && ./a.out
3. 使用 heaptrack 視覺化:
   heaptrack ./program
   heaptrack_gui heaptrack.program.*

場景 2:Rust 程式效能優化

# 完整優化流程
1. cargo build --release
2. cargo flamegraph --bin program
3. 檢視火焰圖,找出熱點
4. cargo bench  # 優化前基準
5. 優化程式碼
6. cargo bench  # 優化後對比

場景 3:高並發服務診斷

# 系統層面
1. ss -s                    # 查看連線統計
2. netstat -nat | awk '{print $6}' | sort | uniq -c  # 連線狀態分佈

# 應用層面(C++)
perf record -g -p `pidof server` -- sleep 30
perf report

# 應用層面(Rust + Tokio)
tokio-console  # 即時查看非同步任務

場景 4:延遲分析

# BPF 追蹤系統調用延遲
bpftrace -e 'tracepoint:syscalls:sys_enter_read { @start[tid] = nsecs; }
             tracepoint:syscalls:sys_exit_read /@start[tid]/ {
                 @ms = hist((nsecs - @start[tid]) / 1000000); 
                 delete(@start[tid]);
             }'

# C++ 程式分析
strace -T -p PID  # 顯示每個系統調用的時間

# Rust 程式分析
RUST_LOG=trace cargo run  # 啟用詳細日誌

🎓 最佳實踐總結

通用原則

  1. 先測量,別猜測 - 使用工具驗證假設
  2. 從全局到局部 - 先看系統整體,再深入細節
  3. 建立基準線 - 保存正常狀態的性能數據
  4. 持續監控 - 使用 Prometheus + Grafana 等工具

C++ 優化建議

  • 編譯時保留符號:-g -fno-omit-frame-pointer
  • 使用 PGO (Profile-Guided Optimization)
  • 善用 perfvalgrind 工具鏈
  • 考慮使用 jemalloctcmalloc

Rust 優化建議

  • 使用 cargo flamegraph 找熱點
  • 善用 criterion 做基準測試
  • 注意 BoxArcRc 的使用開銷
  • 非同步程式使用 tokio-console 診斷

火焰圖解讀技巧

  • 寬度 = 時間佔比
  • 高度 = 調用棧深度
  • 顏色 = 通常隨機,用於區分
  • 找最寬的"平頂山" = 優化目標

📚 延伸資源


💡 記住:性能優化是一門實證科學,永遠要基於數據做決定,而不是直覺!