# Profiling 取自:Brendan Gregg ![image](https://hackmd.io/_uploads/SJ4zPdOXgg.png) 先概覽一下,右側有顏色的方塊代表在 Linux 的硬體或軟體 Component ,黑字分別是可以用的 tool 去 trace 相關的效能議題。 - 有哪些 tool ? - perf - ... - page faults - major - minor ## 視覺化理解 ```mermaid flowchart LR CPU[🧠 CPU] --> TLB["📘 TLB (快取頁面對應)"] TLB -->|✔ 命中| Cache["⚡ Cache (L1/L2/L3)"] Cache -->|✔ 命中| Data[✅ 成功讀資料] Cache -->|❌ Cache Miss| RAM[🧠 RAM] RAM -->|→ 更新 Cache| Cache TLB -->|❌ TLB Miss| PageTable["📄 Page Table (在 RAM)"] PageTable -->|✔ 有對應頁面| TLBUpdate[📥 更新 TLB] TLBUpdate --> Cache PageTable -->|❌ 沒有記錄| PageFault[🚨 Page Fault] PageFault --> Disk[(💽 Disk / Swap)] Disk -->|→ 載入頁面至 RAM| RAM RAM -->|→ 更新頁表 + TLB| TLBUpdate ``` ## 虛擬記憶體存取流程圖 ``` CPU 存取虛擬地址 VA │ ▼ 查 TLB 有無映射(VA → PA) │ ├─✔ 有映射 → 取出實體位址 PA │ │ │ ▼ │ 查 CPU Cache(L1 → L2 → L3) │ │ │ ├─✔ 有資料 → Cache Hit ✅(最快) │ │ │ └─✘ 無資料 → Cache Miss 🚫 │ │ │ ▼ │ 從 RAM 載入資料 → 更新 Cache → 使用 │ └─✘ 無映射 → TLB Miss │ ▼ 查頁表有無該頁面資訊 │ ├─✔ 有:更新 TLB → 回到查 Cache │ └─✘ 無:**Page Fault** ⚠ │ 通知 OS → 從 Disk/SWAP 載入頁面至 RAM ▼ 更新頁表、TLB → 重啟指令 → 查 Cache ``` ## Page Fault ![image](https://hackmd.io/_uploads/ByMxbna7ll.png) - 程式在執行時,嘗試存取一塊目前不在實體記憶體中的虛擬記憶體頁面,導致處理器產生例外中斷,由作業系統處理。 - backgound - Linux 使用 虛擬記憶體(Virtual Memory):每個進程看到的是獨立的虛擬地址空間 - 作業系統會將虛擬記憶體分割為 一頁一頁(Page),通常是 4KB/頁 - 只有程式實際存取頁面時,才會把它從磁碟載入實體記憶體(lazy loading) | 類型 | 描述 | 是否正常 | | ---------------------- | ------------------------------------------------------ | ---------------------- | | **Minor page fault** | 頁面不在 process 的 page table 中,但已在實體記憶體中(如 shared memory) | ✅ 正常,快速處理 | | **Major page fault** | 該頁尚未載入,必須從磁碟或 swap 中讀取 | ⚠️ 成本高,會造成延遲 | | **Invalid (segfault)** | 試圖存取不存在的頁面,或權限錯誤(如寫入唯讀區) | ❌ 系統會發出 `SIGSEGV`,程式當掉 | ## page fault ``` ┌────────────────────────────┐ │ User Program │ │ ─────────────────────── │ │ int *p = malloc(4096); │ │ p[0] = 123; ← 觸發頁錯誤│ └────────────┬───────────────┘ │ ▼ ┌────────────────────────────┐ │ CPU 檢查 Page Table │ │ → 發現該頁不存在(invalid)│ └────────────┬───────────────┘ │ ▼ ┌────────────────────────────┐ │ 發出 Page Fault 中斷 │ │ → 進入 kernel 模式 │ └────────────┬───────────────┘ │ ▼ ┌────────────────────────────┐ │ Linux Kernel Page Fault Handler │ │ 檢查: │ │ ─ 這個地址合法嗎? │ │ ─ 有權限存取嗎? │ │ ─ 是否是映射檔案? │ └────────────┬───────────────┘ │ 合法 │ 非法(非法記憶體) │ │ ▼ ▼ ┌────────────────────────────┐ ┌────────────────────────────┐ │ 從磁碟 / swap 載入該頁面 │ │ 傳送 SIGSEGV,程式崩潰 │ │ 或從 shared memory 拷貝 │ │ Segmentation Fault 錯誤訊息│ └────────────┬───────────────┘ └────────────────────────────┘ │ ▼ ┌────────────────────────────┐ │ 更新 Page Table(將虛擬頁→實體頁) │ └────────────┬───────────────┘ │ ▼ ┌────────────────────────────┐ │ 程式重新執行剛才那一行 │ │ 成功寫入 p[0] = 123 │ └────────────────────────────┘ ``` - major vs minor ``` ┌────────────┐ │ Page Fault │ └────┬───────┘ ▼ ┌────────────┐ │ 該頁是否已載入? │ └──┬───────────┘ │Yes(在記憶體) ▼ ┌──────────────┐ │ Minor Page Fault │ │ → 建立對應 page table│ └──────────────┘ │No(需從磁碟讀取) ▼ ┌──────────────┐ │ Major Page Fault │ │ → 讀磁碟 → 分配頁面│ └──────────────┘ ``` ## page fault vs cache miss | 項目 | **Page Fault(分頁錯誤)** | **Cache Miss(快取未命中)** | | ----------- | ------------------------ | --------------------------- | | **發生時機** | 存取的虛擬頁面尚未載入至主記憶體(RAM) | 存取的資料不在 L1/L2/L3 cache 中 | | **處理方式** | 由 OS 介入處理,可能從磁碟載入資料至 RAM | 由硬體自動從主記憶體(RAM)載入資料到快取中 | | **成本(延遲)** | 非常高,若需從磁碟(或 swap)載入頁面 | 中等偏低,取決於從哪層 cache 到 RAM 的距離 | | **是否中斷程式** | 是,會觸發 exception,由作業系統處理 | 否,通常程式繼續執行,只是稍慢 | | **發生原因** | 虛擬頁尚未對應至有效的實體記憶體 | 欲讀取的資料未被 cache 命中 | | **與記憶體的關係** | 涉及虛擬記憶體管理與頁面交換 | 涉及 CPU cache 系統與資料區域性 | - 直覺理解: - Cache Miss:像你打開冰箱找牛奶,沒看到 → 去儲藏室(RAM)找到了 → 下次記得先放冰箱。 - Page Fault:你打開冰箱找牛奶,發現牛奶根本沒買 → 出門去超商買回來 → 下次記得先放家裡冰箱。 發生路徑上的關聯: CPU 想要讀某個位址 → 查 TLB 是否有對應實體頁(若無則 TLB miss) 若頁面尚未載入 RAM → Page Fault 若頁面已在 RAM,接下來查 cache → 若不在 cache → Cache Miss 如果在 cache → Cache Hit(最快) 總結一句話: Cache Miss 是 CPU 找資料時,快取裡沒命中,需要去 RAM。 Page Fault 是 CPU 找資料時,那頁根本還不在 RAM,需要作業系統把它從磁碟讀進 RAM。 ## TLB miss ![image](https://hackmd.io/_uploads/SJHjd8Cmel.png) ## TLB ![image](https://hackmd.io/_uploads/Ski0g2pXle.png) ![image](https://hackmd.io/_uploads/H1sIZhTQgx.png) ![image](https://hackmd.io/_uploads/S1dDWn6Qlx.png) [Introduction to Memory Management in Linux](https://youtu.be/7aONIVSXiJ8) ```mermaid flowchart TD subgraph CPU&nbsp;Core ALU[ALU / AGU<br>產生虛擬位址] --> VA[Virtual Addr] VA --> TLB{{TLB<br>快取查詢}} end TLB -- 命中 --> MEM[👉 實體記憶體存取] TLB -- 未命中 --> MMU[MMU<br>分頁表走訪] MMU -- 合法 PTE --> FILL[回填 TLB] --> MEM MMU -- 不存在 / 權限錯誤 --> PF[⚡ Page&nbsp;Fault] PF --> OS["OS Page-Fault&nbsp;Handler<br>(核心模式)"] OS -->|換頁 / 配頁| PTU[更新分頁表<br>+ 刷新 TLB] PTU --> RET[返回使用者態,重新執行指令] ``` | 項目名稱 | 中文名稱 | 說明 | 常見用途 | | ------------------ | --------- | --------------------------------------------- | ------------------------ | | `cycles` | CPU 週期數 | 處理器執行的總時鐘週期數 | 評估程式執行時間(與 CPU 頻率相關) | | `instructions` | 指令數 | 已執行的 CPU 指令總數 | 搭配 cycles 計算 IPC(每週期指令數) | | `minor-faults` | 次級缺頁 | 記憶體頁已存在但尚未映射進行處理(無需 I/O) | 分析虛擬記憶體效能 | | `major-faults` | 重大缺頁 | 缺頁時需從磁碟讀取資料(需進行 I/O) | 檢查是否頻繁觸發記憶體分頁 | | `dTLB-loads` | 資料 TLB 載入 | 嘗試載入資料的 TLB(Translation Lookaside Buffer)記錄次數 | 檢查記憶體虛實轉換快取的使用狀況 | | `dTLB-load-misses` | 資料 TLB 失敗 | 資料存取時未命中 TLB,需查詢頁表 | 觀察 TLB 效率,失敗率高表示轉換緩慢 | | `iTLB-loads` | 指令 TLB 載入 | 嘗試載入指令的 TLB 次數 | 評估程式碼虛擬位址快取命中率 | | `iTLB-load-misses` | 指令 TLB 失敗 | 指令存取時未命中 TLB,需查詢頁表 | 指令分頁效率分析,常見於大型 binary | | `page-faults` | 頁面錯誤總數 | 包含 minor 與 major fault 的總數 | 觀察程式在記憶體管理上的負擔 | | `cache-references` | 快取存取次數 | CPU 對 L1/L2/LLC 等快取的總存取次數 | 衡量快取使用頻繁程度 | | `cache-misses` | 快取未命中次數 | CPU 存取快取時未命中的次數 | 評估資料/指令是否常被 cache 命中 | - perf - sudo perf stat - sudo perf record -g - - TODO - gprof | 階段 | 目的 | 常用指令 / 工具 | | -------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------ | | **快速量化 (粗粒度)** | 先確認 CPU/記憶體/IO 是否飽和,判斷是哪一類瓶頸 | `top`、`htop`、`vmstat`、`iostat`、`dstat` | | **抽樣分析 (中粒度)** | 找出「最耗時的函式/路徑」 | `perf stat / top / record + report`、`BPFtrace`、`FlameGraph` | | **精細診斷 (細粒度)** | 深入微架構(Cache、分支、TLB 等)、鎖競爭、系統呼叫 | `perf stat -e ...`、`perf annotate`、`perf c2c / lock`、`ftrace`、`eBPF + BCC/BPFtrace`、`valgrind` (massif/cachegrind) | perf、ftrace、eBPF、kgdb、kprobes ### Links - [A Beginner's Guide to Linux Performance Profiling: From First Principles to Flamegraphs](https://hackmd.io/@alanhc/profiling-101) - gui - [Profiling CPU and Memory on Linux, with Opensource Graphical Tools - David Faure, KDAB - linux foundation](https://youtu.be/HOR4LiS4uMI) - [Inspecting and Optimizing Memory Usage in Linux - João Marcos Costa, Bootlin](https://youtu.be/pIR1H7ZyWe4) - ["Tracing, Profiling & Debugging in Production (eBPF)" - Trent Lloyd (PyCon AU 2019)](https://youtu.be/jXzEzmz-oag) - [Linux Performance Tools, Brendan Gregg, part 1 of 2](https://youtu.be/FJW8nGV4jxY) - [Velocity 2017: Performance Analysis Superpowers with Linux eBPF](https://youtu.be/bj3qdEDbCD4?si=bt9DVyikG1jHfmXt) 效能分析的本質是: > 🔑 效能(Performance)= 有用的工作(Useful Work)÷ 所花的時間(Time) 換句話說: - 我們的程式到底做了多少有意義的工作? - 做這些工作的過程中花掉的時間在哪裡? - 如果慢,到底慢在什麼資源?如何確認? ## 什麼是效能? 效能可以被分解為最根本的三個資源維度: | 資源類型 | 代表指標 | 第一性原理的根本限制 | |----------------|-------------------------------|-------------------------------------------| | **CPU** | 指令數量、IPC、使用率 | CPU 是有限的時脈驅動狀態機,只能每 cycle 做有限工作 | | **Memory** | cache miss、TLB、page fault | 記憶體存取受到階層結構與時延限制(memory wall) | | **I/O** | IO wait、latency | 裝置響應時間、佇列設計、吞吐量有限 | | 資源類型 | 第一性限制(根本物理限制) | 常見瓶頸現象 | | ------- | ---------------------- | ------------------------------- | | 🖥️ CPU | 每個 cycle 執行固定數量的指令 | CPU 飽和、IPC 太低 | | 💾 記憶體 | 存取速度受到階層結構與 latency 限制 | Cache miss、Memory wall、TLB miss | | 🔄 I/O | 外部裝置存取速度受限於硬體 | I/O wait、device latency | ## 為何要進行效能分析? 在資源限制的前提下,盡可能提升有用工作的比例,減少無效等待或浪費。 ## 效能劣化的基本來源有哪些?(來自物理與系統設計限制) | 基本現象 | 第一性原因解釋 | |---------------------|----------------------------------------------------------| | CPU 飽和 | 指令數量過多、無法並行處理、等待其他資源(如記憶體) | | Cache Miss | 資料位置分散、不符合 spatial/temporal locality | | Page Fault | 虛擬記憶體機制導致非預期 I/O(memory access latency) | | Context Switch | 多任務切換導致保存/還原狀態、TLB/cache flush 等 overhead | | Lock Contention | 多執行緒同時搶奪資源,造成序列化 | | I/O Bottleneck | 磁碟、網路等裝置 throughput 無法滿足需求 | ## 效能分析的工具選擇與使用時機 | 階段 | 你在問的問題 | 常見工具 | 工具特性 | | ----------- | ----------------------- | ------------------------------------------- | --------------- | | ① 基本時間量測 | 程式整體到底花多少時間? | `time`, `hyperfine` | 快速簡單,取得初步效能數據 | | ② 系統資源使用 | CPU/Memory/I/O 哪個資源是瓶頸? | `top`, `htop`, `vmstat`, `iotop` | 快速定位整體瓶頸資源 | | ③ CPU 細部分析 | IPC 高嗎?Cycles 浪費在哪? | `perf stat`, `ocperf`, `pmu-tools` | 提供細緻的 CPU 硬體指標 | | ④ 熱點函式定位 | 哪個函式或程式段落最耗時? | `perf record/report`, `gprof`, `FlameGraph` | 提供函式級別精確定位 | | ⑤ 函式呼叫關係 | 函式呼叫誰、多少次、每次多久? | `uftrace`, `ltrace` | 清楚展示 call graph | | ⑥ 記憶體耗用 | 記憶體用多少?峰值在哪裡? | `valgrind massif`, `heaptrack` | 檢查記憶體峰值、leak | | ⑦ Cache行為分析 | L1/L2 cache有效使用嗎? | `cachegrind`, `callgrind`, `perf c2c` | 展示 Cache 細部效能 | | ⑧ 低負擔線上追蹤 | Production 可用的長期低成本追蹤? | `eBPF` (`bcc`, `bpftrace`) | 長期觀測,幾乎不影響效能 | ## 整體分析流程(效能分析 Roadmap) ```mermaid graph LR A[① 量化整體時間 time/hyperfine] --> B[② 觀察資源使用 top/iotop] B --> C[③ 深入 CPU 指標 perf stat] C --> D[④ 熱點函式 perf record + FlameGraph] D --> E[⑤ 函式呼叫關係 uftrace] E --> F[⑥ 記憶體峰值 massif] F --> G[⑦ Cache 行為 cachegrind] G --> H[⑧ 長期追蹤 eBPF/bpftrace] ``` ## 分析流程 1. **觀察輸出行為** - 為什麼慢?延遲在哪? - 常用指標:wall-clock time、throughput、latency 2. **建立模型** - T = CPU Time + Wait Time + I/O Time - CPU Time = Instructions / IPC × Cycle Time 3. **找出資源瓶頸** - 工具:perf、uftrace、ftrace、top、iotop、vmstat 等 4. **回推到根本原因** - 是不是 cache miss?是不是鎖?是不是 syscall?是不是 scheduler 不公平?是不是 memory bandwidth 被佔用? 5. **優化策略根據本質制定** - 減少 I/O 次數(避免 page fault) - 減少 thread 間 contention(使用 lock-free 結構) - 利用資料 locality(避免 cache miss) - 改寫演算法使得計算時間減少(例如 FFT vs naive DFT) ### perf #### 用途 `perf` 是 Linux 下用於分析效能瓶頸的核心工具,適用於從系統層級到函式層級的 CPU profiling、cache miss 分析與系統事件統計。 #### 使用時機 - 想知道「哪裡跑得最久」:找出 CPU 熱點與 call graph - 想知道「整體是否有效率」:透過 `perf stat` 觀察 IPC、cache miss、cycles - 需要生成火焰圖以視覺化熱點區段時 - 觀察 kernel 與 userspace 混合行為 #### 常見用法 ```bash # 統計整體效能指標(IPC、cache miss 等) perf stat ./your_program # 收集 call graph 與 hot spot 分析 perf record -g ./your_program perf report # 火焰圖:輸出資料並產生視覺圖形 perf record -F 99 -a -g -- ./your_program perf script > out.perf stackcollapse-perf.pl out.perf > out.folded flamegraph.pl out.folded > flamegraph.svg ``` #### 優點 - 不需修改程式即可進行 profiling - 支援多種硬體事件(如 instructions、cycles、cache miss) - 可深入分析 kernel 與 user 空間行為 - 可輸出火焰圖等視覺化工具 #### 缺點 - 有些功能需 root 權限執行 - 精確分析需符號表與 debugging symbols - 在 container 或 restricted 環境下可能受限 #### 實務建議 - 進行任何優化前,先用 `perf stat` 量化基本效能 - 用 `perf top` 即時觀察熱點,再進行 `perf record` 深入分析 - 建議搭配火焰圖視覺化觀察瓶頸集中區域 - 生產環境建議短時取樣,避免過多 overhead ### ftrace #### 用途 `ftrace` 是 Linux kernel 內建的 tracing framework,用於追蹤核心行為(context switch、IRQ latency、function call、syscall 等),可幫助系統工程師深入分析排程延遲、系統抖動(jitter)與低階效能問題。 #### 使用時機 - 排查系統異常抖動、長時間卡住的 root cause - 驅動程式與 kernel module 的效能瓶頸分析 - 觀察 scheduler 運作、task 切換行為 - 和 `perf` 搭配進行全系統觀察 #### 常見用法 ```bash # 啟用 function tracer sudo echo function > /sys/kernel/debug/tracing/current_tracer # 過濾特定函式,例如 do_sys_open sudo echo do_sys_open > /sys/kernel/debug/tracing/set_ftrace_filter # 啟動與觀察 trace sudo cat /sys/kernel/debug/tracing/trace # 清除 trace buffer sudo echo > /sys/kernel/debug/tracing/trace ``` 也可透過 wrapper 工具如 `trace-cmd`、`kernelshark` 提供更佳的使用體驗與 GUI 支援。 #### 優點 - 原生支援於 kernel,無需額外安裝 - 能夠精確觀察 scheduler 與 interrupt 層級活動 - 適合分析 low-latency 系統與 driver - 支援多種 tracer(function、irqsoff、sched_switch 等) #### 缺點 - 操作複雜,需要熟悉 debugfs 與 kernel trace 環境 - 輸出資訊可能過於繁雜,需搭配過濾條件使用 - 僅適用於 kernel space,不適合使用者空間 profiling #### 實務建議 - 若觀察 jitter 或 latency spike,先從 `sched_switch` 分析上下文切換時間 - 可搭配 `trace-cmd report` 彙整更清晰的事件序列 - 驅動或 kernel module 最佳化常需搭配 `ftrace` 佐證 ### 火焰圖分析(Flamegraph) #### 用途 火焰圖是一種視覺化工具,用於顯示 CPU 使用的函式堆疊與時間分佈。它可以幫助你一眼看出哪些函式佔用最多執行時間,適合用於分析 hot path 與瓶頸函式。 #### 使用時機 - 程式效能下降但原因不明 - 想快速定位執行時間集中在哪些函式 - 與團隊溝通效能瓶頸時需要可視化證據 - 對函式調用深度與寬度有整體認知需求 #### 建立流程(以 perf 為例) ##### 安裝工具(以 Ubuntu 為例) ```bash sudo apt install linux-tools-common linux-tools-$(uname -r) \ git build-essential -y # 安裝 flamegraph 腳本集 git clone https://github.com/brendangregg/Flamegraph.git cd Flamegraph ``` ##### 收集資料並產出圖表 ```bash # 收集 profile 資料(建議搭配 -F 控制取樣頻率) perf record -F 99 -a -g -- ./your_program # 轉換成 stack trace 格式 perf script > out.perf # 產出 flamegraph 所需格式 ./stackcollapse-perf.pl out.perf > out.folded # 繪製火焰圖 ./flamegraph.pl out.folded > flamegraph.svg ``` #### 火焰圖說明 - **橫向長度**:表示總執行時間佔比(越長越慢) - **縱向堆疊**:表示函式呼叫鏈深度 - **每一條方塊**:表示一個函式,可滑鼠懸停看名稱與時間 #### 優點 - 非常直觀、便於發現效能熱點(hot path) - 不需修改原始碼,可在已編譯程式上取樣 - 適合大規模應用程式的全域視角效能分析 #### 缺點 - 須搭配 `perf` 或其他 trace 工具收集資料 - 多執行緒與 async 程式容易堆疊混亂,需清理堆疊資料 - 需花時間學習解讀技巧 #### 實務建議 - 可定期在開發週期進行一次火焰圖分析做為基準比較 - 遇到 CPU 使用異常高時優先繪製火焰圖定位 - 可搭配分支、cache miss 事件產生不同維度火焰圖 ### valgrind #### 用途 `valgrind` 是一套動態分析工具,最常用於記憶體錯誤偵測、資源洩漏分析與 cache 效能模擬。 核心工具包含: - `memcheck`: 偵測未初始化記憶體讀取、非法存取、記憶體洩漏等問題 - `cachegrind`: 分析 cache miss、分支預測命中率 - `callgrind`: 分析函式呼叫次數與執行時間(可搭配 KCachegrind 視覺化) #### 使用時機 - 開發早期測試記憶體正確性與釋放邏輯 - 找出 segmentation fault 原因 - 想量化不同演算法對 cache 行為的影響(例如排序) - 搭配 `callgrind` 作為簡易函式 profiling 工具 #### 常見用法 ```bash # 偵測記憶體使用錯誤與洩漏 valgrind --leak-check=full ./your_program # 偵測未初始化記憶體、越界存取 valgrind --track-origins=yes ./your_program # 分析 cache 行為 valgrind --tool=cachegrind ./your_program cg_annotate cachegrind.out.* # 函式呼叫分析 valgrind --tool=callgrind ./your_program callgrind_annotate callgrind.out.* ``` #### 優點 - 偵錯能力強,可定位難以重現的記憶體問題 - 可模擬硬體 cache 行為,便於調整資料結構或演算法 - callgrind 與 cachegrind 支援詳細報告與視覺化工具(如 KCachegrind) #### 缺點 - 執行非常慢,通常為原始速度的 10~50 倍 - 不支援多執行緒間同步錯誤偵測 - 僅支援 x86/x86_64 架構,其他平台相容性差 #### 實務建議 - 開發初期強烈建議整合至測試流程中,提早發現潛藏 bug - 對效能敏感邏輯(如排序、數值計算)可搭配 `cachegrind` 模擬最佳化潛力 - 呼叫行為分析可導出 callgrind 檔並使用 KCachegrind 互動視覺化分析 ### gdb + core dump 分析流程 #### 為何需要? 在生產環境中,程式可能會因為 segmentation fault、abort、assertion fail 等異常崩潰。當你無法重現這些錯誤時,**core dump 是唯一可以還原當下狀態的線索來源**。 使用 `gdb` 搭配 core dump 可以: - 查看崩潰當下是哪一行程式碼造成的錯誤 - 還原呼叫堆疊(stack trace)與變數內容 - 檢查記憶體狀態與指標有效性 - 協助判斷邏輯錯誤、資源釋放順序等問題 #### 使用時機 - 程式 crash 且無法用 valgrind 或 log 重現時 - 使用者回報錯誤但無法完整還原操作流程時 - CI/CD 環境中需自動收集失敗樣本進行事後分析 #### 如何啟用 core dump? ```bash # 設定 core dump 開啟與檔案大小(ulimit 預設為 0) ulimit -c unlimited # 指定 core 檔儲存路徑(Linux) echo "/tmp/core.%e.%p" | sudo tee /proc/sys/kernel/core_pattern ``` #### 撰寫可除錯的程式(加上 debug symbol) ```bash g++ -g -o myprog main.cpp ``` #### 使用 gdb 分析 core dump ```bash # 假設 myprog 是執行檔,core.12345 是 dump 檔 gdb ./myprog core.12345 # 在 gdb 內常用指令: (gdb) bt # 顯示 backtrace(函式呼叫堆疊) (gdb) frame 0 # 切到崩潰當下的堆疊框架 (gdb) info locals # 查看區域變數 (gdb) list # 顯示錯誤行附近原始碼 ``` #### 優點 - 還原問題現場,不必重現也能追蹤 root cause - 可搭配 CI/CD 自動收集並分類 crash case - 支援多種架構與平台(cross-debug 也可) #### 缺點 - 需事先保留 core 檔與 debug symbol - 無法分析邏輯錯誤(只能抓 runtime 異常) - 不適合即時效能 profiling(但可作為後續定位工具) #### 實務建議 - 開發階段加入 `-g` 編譯選項與 `INHIBIT_PACKAGE_STRIP = "1"`(如 Yocto) - 保留執行檔與 core dump,並統一命名便於自動分析 - 可撰寫腳本自動用 gdb 對 core dump 執行 `bt` 並儲存堆疊 ## TODO - vmstat 1 - iostat 1 - network - netstat -a - sar - mpstat 1 - pidstat