百萬行專案、完整建置動輒數小時,即使增量建置也常需等待數分鐘。本文從「減少工作量」與「增加算力」兩大維度,給出 20+ 條經實戰驗證的加速策略。
頭檔中僅用到指標/參考的類別,改用 class Foo; 前置宣告,將 #include "Foo.h" 移至 .cpp。阻斷傳遞性包含爆炸。
// Widget.h
class Widget {
struct Impl; std::unique_ptr<Impl> pImpl;
public:
Widget(); ~Widget();
void doWork();
};
// Widget.cpp 才包含完整定義
介面與實作完全分離,實作變更不觸發依賴它的單元重新編譯。
Common.h 包含全世界。#include 圖譜,拆分熱點頭檔。自動化腳本(如 include-what-you-use、Clang Tooling)掃描並移除未使用的 #include。曾單專案清理 5000+ 行冗餘包含。
兩者強制實作置於頭檔,膨脹編譯單元。
- 熱點函式才加 inline。
- 模板實作放 .inl 或 .tcc,頭檔僅 #include 它,必要時顯式實例化常用型別移至 .cpp。
穩定、常用、巨大的頭檔(STL、Boost、專案核心頭檔)放入 stdafx.h / pch.h。單專案內避免重複解析,提速 2-5 倍。
將多個 .cpp #include 至單一 all.cpp 編譯。
優點:單編譯單元、單目標檔、鏈接快、符號解析快。
缺點:命名衝突風險、失去並行編譯粒度、增量建置失效。
策略:僅對穩定、低變更率的模組啟用(如第三方庫封裝層)。
基於內容雜湊的編譯緩存。同源碼、同編譯選項、同編譯器版本 → 直接復用目標檔。
痛點:MSVC 官方不支援。替代方案:clcache、sccache (支援 MSVC)、自建 cl.exe 包裝腳本。
Additional Include Directories 超過 50 個會嚴重拖慢頭檔搜尋。模組化管理:每個模組僅暴露公開介面目錄,內部實作目錄不對外透出。
32 核心 Threadripper / Xeon W / EPYC,配合 /MP (MSVC) 或 -jN (Ninja/Make),編譯階段近線性加速。
編譯密集 I/O:讀頭檔、寫 .obj/.pdb/.pch。
- 專案放在 NVMe RAID 0 或 RAM Disk (tmpfs)。
- TEMP/TMP 導向高速磁碟。
- 關閉防毒軟體即時掃描專案目錄。
利用閒置工作站/建置伺服器 CPU。
- Incredibuild:Visual Studio 深度整合、虛擬檔案系統、授權費高但企業級支援完善。
- 百核心集群可將 4 小時全建壓縮至 10 分鐘內。
若 Solution B 依賴 Solution A,傳統串行建置耗時 T_A + T_B。
並行策略:
1. 同時啟動 A 與 B 編譯階段。
2. B 的編譯只需 A 的頭檔/匯入庫,不需 A 完整鏈接完成。
3. A 鏈接完成後,觸發 B 的重新鏈接(極快)。
總耗時 ≈ max(T_A_compile, T_B_compile) + T_A_link + T_B_link。
| 優先級 | 措施 | 預期收益 | 實施成本 |
|---|---|---|---|
| P0 | PCH + 精簡 Include 路徑 | 30-50% | 低 |
| P0 | 前置宣告 + Pimpl 熱點類別 | 20-40% | 中 |
| P1 | ccache/sccache + 統一編譯選項 | 重建 80%+ | 中 |
| P1 | 模組化拆分、移除萬用頭檔 | 長期複利 | 高 |
| P2 | Unity Build 穩定模組 | 單模組 5-10x | 中 |
| P2 | 32+ 核心建置機 + NVMe | 2-4x | 硬體成本 |
| P3 | Incredibuild 集群 | 10-50x | 授權+維運 |
編譯加速無銀彈,只有系統性工程。從「寫給編譯器看的程式碼」入手,疊加工具鏈優化、硬體投資、分散式擴展,才能將等待時間壓縮至「思考間隙」,讓開發者進入心流狀態。