.NET Core 跨平台 #5, 多工運算效能大考驗 – 計算圓周率測試
問題與答案 (FAQ)
Q&A 類別 A: 概念理解類
A-Q1: 什麼是 CPU Bound 運算?
- A簡: 主要受限於處理器計算資源,I/O與記憶體占用低。適合評估純運算與平行化效益。
- A詳: CPU Bound 指程式的瓶頸在處理器運算,而非磁碟或網路等 I/O。特徵是運算迴圈密集、記憶體配置穩定、I/O 呼叫少。本文選用計算圓周率高位數作為測試,因其幾乎完全消耗 CPU,不需大量記憶體或 I/O,能隔離出 JIT/原生編譯與執行緒排程對效能的影響。此類工作非常適合用平行化來提升吞吐,但效益會受可用核心數、排程策略與超執行緒等因素影響。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q2, A-Q9, B-Q1
A-Q2: 為何以計算圓周率測試 .NET Core 跨平台效能?
- A簡: 圓周率高位數計算屬CPU重、I/O輕,能公平比較JIT與排程差異。
- A詳: 測試目標是比較不同作業系統與部署型式下 .NET Core 的 CPU Bound 效能。圓周率高位數計算需大量整數/浮點運算,卻幾乎不受 I/O 與記憶體配置干擾,是理想的基準工作負載。透過同時執行多次計算,可觀察 Task/ThreadPool 的排程策略在 1/2/4/8 核心下的放大效果,並以總時間、平均時間與效率提升率三項指標整體衡量平台差異。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q1, A-Q5, A-Q7
A-Q3: .NET 的 Task 是什麼?和執行緒有何關係?
- A簡: Task 是建構於 ThreadPool 的工作單位,提供更高層抽象的非同步與平行運算。
- A詳: System.Threading.Tasks.Task 將工作描述為可排程的單位,交由 ThreadPool 配置到可用執行緒上。相對 Thread 的顆粒度與生命週期控制,Task 更專注在「做什麼」而非「在哪個執行緒做」。TaskScheduler 會依系統負載調整併發度,避免過度建立執行緒造成切換成本,並提供等候、取消、延續等高階能力。本文測試以預設 Task/ThreadPool 策略進行,以反映平台預設行為。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: B-Q1, B-Q2, A-Q4
A-Q4: Task 與 Thread 有何差異?
- A簡: Thread 是執行單元;Task 是工作抽象,通常交由ThreadPool排程執行。
- A詳: Thread 代表 OS 層級的執行緒,建立/銷毀與切換成本高。Task 是邏輯工作,預設會使用 ThreadPool 中重複利用的背景執行緒承載。Task 更易組合、取消與例外傳遞,且由 TaskScheduler 控制併發度,降低過度併發導致的資源競爭。本文以 Task 反映 .NET 預設排程智慧,避免手動 Thread 管理干擾測試。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q3, B-Q1, B-Q2
A-Q5: 什麼是 Total Execute Time(總執行時間)?
- A簡: 從測試開始啟動到所有任務完成的總耗時。越短代表整體效能越好。
- A詳: 總執行時間定義為併發啟動所有任務後,直到最後一個任務完成的時間跨度。它反映了工作排程、JIT/原生編譯、CPU運算與平台開銷的綜合結果。若要比較平台的基本運算速度(排除多工優勢),可聚焦在 1 核心環境的總時間。本文用此指標評估跨 OS/容器的整體表現。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q6, A-Q7, B-Q6
A-Q6: 什麼是 Average Execute Time(平均執行時間)?
- A簡: 所有任務個別完成時間的平均值。越短表示單一任務效率佳。
- A詳: 平均執行時間是將每個 Task 的實際完成時間取平均,用於衡量個別任務的執行效率與排程公平性。總時間受最慢任務與併發度影響,平均時間則更敏感地反映單一工作在不同平台上的純運算效率與 JIT 成效。本文觀察到核心數提高時,平均時間增幅趨緩,顯示 ThreadPool 有效控制同時執行的工作數。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q5, B-Q6, B-Q2
A-Q7: 什麼是 Efficiency Rate(效率提升率)?如何計算?
- A簡: 以單任務基準估算平行處理帶來的整體效能提升百分比。
- A詳: 效率提升率用來量化平行化的效益。以 1 核心、單任務的總時間為基準 base。若沒有平行處理,執行 N 個任務需 (total-base)×N 時間;實際平行總時間為 total。效率提升率 = ( (total - base) × N ) / total × 100%。此指標整合了排程、併發與平台開銷,能比較不同核心數與平台的平行效益。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: B-Q5, A-Q5, A-Q6
A-Q8: 為何用效率提升率衡量平行處理?
- A簡: 它衡量從序列到平行的收益,跨平台與核心數具可比性。
- A詳: 直接比較總時間可能受 JIT、基礎運算速度、OS 開銷等干擾。效率提升率以「同一工作在同環境單任務」為基準,衡量多任務同時執行的加速效果,能更純粹地反映排程與多核心利用度。特別在跨平台情境下,它有助於分離平台基礎性能與平行化帶來的邊際收益。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q7, B-Q5, B-Q6
A-Q9: 平行處理與多核心的關係為何?
- A簡: 核心數決定可同時真正並行的工作數,平行化效益受其限制。
- A詳: 平行處理透過同時執行多個工作來縮短牆上時間,但真正的並行需硬體核心支援。當任務數不超過核心數,總時間大致不隨任務數增加而增加;超過後將競爭 CPU,效益遞減。本文數據顯示在 1 核下任務加倍時間近似加倍,而在多核下總時間在核心未飽和時趨於平坦。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: B-Q19, A-Q10, B-Q1
A-Q10: 超執行緒(Hyper-Threading)對效能有何影響?
- A簡: 提升吞吐但不等同核心加倍;對CPU Bound工作提升有限。
- A詳: 超執行緒讓每個實體核心同時發出兩條硬體執行緒,改善管線閒置與資源利用。對運算密集且單位時間飽和算力的工作,其提升通常低於新增實體核心。本文在 4 核 8 執行緒的 i7-2600K 上觀察到 8「核」配置的增益低於 4 核到 4 核之間的比例增益,符合 HT 的特性。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: B-Q10, B-Q19, D-Q7
A-Q11: 為何比較多種 OS 與容器環境?
- A簡: 觀察 JIT、執行緒管理與系統開銷的跨平台差異與最佳化。
- A詳: 即使使用同一 CoreCLR,底層 OS 的執行緒排程、系統呼叫開銷與計時器精度皆不同;容器/虛擬化也帶入額外層級。比較 Windows Server 2012 R2、Windows Server 2016(Nano/Container)、Ubuntu + Docker、Boot2Docker,可觀察 .NET Core 在自家與異質平台上的最佳化差異與排程行為對效能的實際影響。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q14, B-Q3, B-Q7
A-Q12: 為何用 VM 控制硬體資源(1/2/4/8 核)?
- A簡: 統一硬體條件,隔離平台差異,公平比較多核伸縮性。
- A詳: 以相同主機、相同 VM 規格(記憶體、磁碟、顯示等),只調整虛擬核心數,能降低硬體差異造成的偏誤,專注觀察平台與排程策略在不同併發度的伸縮性。本文使用相同 VM 模板,配置 1/2/4/8 核心重複測試,確保比較公平。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: B-Q7, C-Q7, A-Q9
A-Q13: 在 1 核環境中平行化是否有助益?
- A簡: 幾乎無助益,甚至因排程與同步開銷而略慢。
- A詳: 1 核下所有任務仍需輪流執行,平行化主要引入 Task/ThreadPool 排程與工作切換的額外成本,無法帶來真正並行。本文觀察到 1 核時任務數加倍,總時間近似線性增加,符合預期。若目標環境常為單核心,應以序列或低併發策略為主。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: B-Q1, B-Q6, D-Q3
A-Q14: .NET Core 在 Windows 與 Linux 的效能差異總結?
- A簡: 整體 Windows 家族領先;與 Ubuntu 差距約一成,非壓倒性差距。
- A詳: 實測顯示除 1 核下 Boot2Docker 略勝外,多核場景 Windows Server 家族整體領先;Windows Server 2016(TP4 + Container)於 4/8 核表現最佳。Ubuntu + Docker 在平均時間上落後,顯示 JIT/排程與 OS 開銷的綜合差異。不過最佳與次佳差距約 10.4%,平台選擇仍需兼顧維運、相容性與成本。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q11, B-Q3, B-Q18
A-Q15: Nano Server 與 Server Core 有何差異與意義?
- A簡: Nano 更精簡、組件更少;有助降低系統開銷與攻擊面。
- A詳: Server Core 是無 GUI 的精簡 Windows 伺服器;Nano Server 更進一步移除非必要元件,採高度模組化,適合容器化與雲端工作負載。本文在 Nano + Windows Container 環境觀察到多核 CPU Bound 測試的良好表現,推測與精簡化減少背景服務與系統開銷有關。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: B-Q7, B-Q18, C-Q4
A-Q16: 容器(Docker)與原生執行的差異?
- A簡: 容器共用主機核心,開銷輕於 VM;但仍有隔離與映像層成本。
- A詳: 容器並不虛擬硬體,隔離度透過命名空間與資源控制實現,啟動快、開銷小。對 CPU Bound 工作,容器開銷通常極低;但映像層、檔案系統與資源限制仍可能影響結果。本文使用 Ubuntu + Docker 與 Boot2Docker 進行比較,顯示容器的輕量特性在 1 核時帶來些許優勢。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: B-Q8, C-Q5, C-Q6
A-Q17: 為何 Boot2Docker 在 1 核表現最佳?
- A簡: 系統極精簡、背景負載低,減少單核資源競爭與排程開銷。
- A詳: Boot2Docker 以極小的 Linux 映像提供 Docker 環境,背景服務與守護程式較少,使單核心下可用 CPU 時間更集中於測試進程。本文觀察 1 核時 Boot2Docker 總時間最佳;但多核放大後,Windows 家族的排程與 JIT 最佳化仍領先。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q16, B-Q8, A-Q14
A-Q18: JIT/原生編譯對 CPU Bound 測試影響?
- A簡: 影響指令品質與暫存器利用,直接左右純運算效能。
- A詳: JIT(即時編譯)將 IL 轉成機器碼,其內聯、暫存器配置與指令選擇會影響算力發揮。不同 OS 與執行階段對 JIT 管線與原生最佳化掌握度不同,會導致平台差異。本文結論推測 Windows 對 binary 與執行緒管理最佳化較成熟,是其領先原因之一。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: B-Q11, B-Q12, A-Q14
A-Q19: 本測試的限制與變因有哪些?
- A簡: 受演算法、JIT版本、計時精度、虛擬化與背景負載影響。
- A詳: 雖盡量控制環境,仍有多項變因:圓周率演算法與實作差異、CoreCLR/JIT 版本差異、Stopwatch 計時精度與時間源、VM 排程與主機負載、容器映像與檔案系統層、超執行緒與 CPU 頻率調節等。結果解讀應聚焦於趨勢與相對比較,並以多次重複測量降低偶然誤差。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: B-Q7, D-Q1, D-Q5
A-Q20: 選擇部署平台除了效能還該考量什麼?
- A簡: 維運成本、相容性、生態工具、安全性與團隊熟悉度。
- A詳: 本文最佳與次佳差距約 10.4%,實務上常難以感知。平台選擇更應考量:既有系統相容性、監控/部署/診斷工具、生態資源、團隊技能、更新與安全維護、容器化策略與成本。將效能視為多指標之一,綜合決策較為穩妥。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q14, C-Q4, C-Q5
Q&A 類別 B: 技術原理類
B-Q1: .NET 的 Task 調度如何運作?
- A簡: 由 TaskScheduler 將 Task 指派 ThreadPool 執行,動態調整併發度。
- A詳: 原理說明:Task 代表待執行工作,預設由 ThreadPool 背景執行緒承載;TaskScheduler 觀測工作佇列與系統負載,採工作竊取等策略分配。流程:建立多個 Task → 併發排入佇列 → ThreadPool 取出執行 → 完成回報。核心組件:Task、TaskScheduler、ThreadPool、工作佇列。此機制避免過度建立執行緒,降低切換成本並提升 CPU 利用。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q3, A-Q4, B-Q2
B-Q2: ThreadPool 如何控制執行緒數量?
- A簡: 以啟發式演算法調整,根據工作積壓與完成率自動增減。
- A詳: 原理說明:ThreadPool 追蹤待處理工作量與完成速度,估算是否需要新增或回收執行緒。流程:初始化最小執行緒 → 負載上升時逐步增補 → 負載下降時回收。核心組件:全域佇列、工作竊取佇列、調整邏輯(min/max threads)。此設計避免 oversubscription,維持良好平均時間與總時間的平衡。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q6, B-Q1, D-Q6
B-Q3: .NET Core 在 Windows 與 Linux 的執行緒/排程差異?
- A簡: 共用 CoreCLR,但依賴底層 OS 排程與系統呼叫,行為與開銷不同。
- A詳: 原理說明:CoreCLR 在兩者上層一致,但 Thread 與計時、同步原語最終落在 Win32/NT 或 Linux syscalls/調度器。流程:Task → ThreadPool → OS 調度 → CPU 執行。核心組件:CoreCLR、OS 調度器、計時器/時鐘源。本文實測顯示 Windows 家族在多核 CPU Bound 表現較佳,反映 OS 層面的最佳化差異。
- 難度: 高級
- 學習階段: 進階
- 關聯概念: A-Q11, A-Q14, B-Q7
B-Q4: 計算圓周率的運算特性為何?
- A簡: 長迴圈、精確大數/浮點運算密集,I/O與分配極少,屬純CPU負載。
- A詳: 原理說明:高位數圓周率計算通常依賴高迴圈次數與高精度數學運算(任意精度整數/浮點)。流程:初始化常數 → 疊代計算部分和/項 → 聚合輸出。核心組件:數學核心(大數/高精度)、迴圈控制、最終輸出。此負載能凸顯 JIT/原生編譯品質與執行緒排程的真實影響。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q1, A-Q2, B-Q12
B-Q5: 效率提升率公式如何推導與使用?
- A簡: 以單任務時間為基準,估算序列總時間與實測總時間之比。
- A詳: 原理說明:假設無平行化,N 任務序列時間 ≈ (total_base)×N;實測平行總時間為 total。流程:測得 base(單任務)、測得 total(N 任務)、代入公式 (total-base)×N/total×100%。核心組件:基準時間 base、任務數 N、實測總時間 total。用此指標比較不同核心/平台的平行收益,避免被基礎算力差異混淆。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q7, A-Q8, B-Q6
B-Q6: 總時間與平均時間的數學關係與意義?
- A簡: 總時間受最慢任務與併發度影響;平均時間反映單任務效率。
- A詳: 原理說明:總時間≈最大完成時間,受排程、核心數與負載平衡影響;平均時間=各任務時間平均,更敏感於單任務執行效率與 JIT 品質。流程:收集每任務耗時 → 求平均/最大。核心組件:時間量測(Stopwatch)、任務集合。兩者搭配可分辨平行度與單核算力對結果的不同貢獻。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q5, A-Q6, B-Q5
B-Q7: 虛擬化如何影響 CPU 排程與計時?
- A簡: Hypervisor 介入排程與時鐘虛擬化,帶來微小但可測的開銷與漂移。
- A詳: 原理說明:VM 的 vCPU 需映射至 pCPU,Hypervisor 會在多租環境中切換與分配;時間來源可能由虛擬時鐘提供,精度與穩定性略受影響。流程:客體 OS 調度 → Hypervisor 映射 → 主機 CPU 執行。核心組件:Hypervisor、vCPU/pCPU、虛擬時鐘。本文用相同 VM 規格控制變因,降低虛擬化差異造成的偏誤。
- 難度: 高級
- 學習階段: 進階
- 關聯概念: A-Q12, D-Q5, C-Q7
B-Q8: 容器對 CPU 執行的影響機制?
- A簡: 共用主機核心與調度器,開銷小;資源限制與檔案層仍可能影響。
- A詳: 原理說明:容器不虛擬硬體,進程直接由宿主 OS 調度;cgroup/namespace 提供資源與隔離。流程:容器進程啟動 → OS 調度 → CPU 執行。核心組件:cgroups、namespace、檔案系統層。CPU Bound 工作容器開銷極低,但若啟用 CPU 配額或使用多層檔案系統,仍可能影響結果。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q16, C-Q5, D-Q4
B-Q9: 為何多任務數(16/32/64)不一定提升吞吐?
- A簡: 超過核心數會爭用 CPU,切換成本與快取失效率升高。
- A詳: 原理說明:任務數遠大於核心數時,OS 與 ThreadPool 頻繁切換上下文,L1/L2 快取未命中率提升,反而降低效率。流程:任務併發超額 → 排程競爭 → 切換 → 效率下滑。核心組件:ThreadPool、OS 調度器、CPU 快取。本文平均時間變化趨緩,顯示 ThreadPool 有效壓抑過度併發。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q6, B-Q2, D-Q2
B-Q10: 超執行緒(HT)的硬體原理與限制?
- A簡: 單核心雙執行緒共享資源以填滿管線,對飽和算術負載提升有限。
- A詳: 原理說明:HT 藉由複製部分前端狀態,讓兩條執行緒共享同一核心的執行資源(ALU、快取)。流程:兩執行緒交錯發送 → 管線空隙被利用。核心組件:執行單元、快取、分派器。對記憶體延遲或分支密集負載提升較顯著;對高度算術飽和負載,增益有限。本文觀察與此一致。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q10, D-Q7, B-Q19
B-Q11: JIT 在跨平台下可能出現的差異?
- A簡: 內聯、暫存器配置與指令選擇策略不同,導致平台效能差異。
- A詳: 原理說明:JIT 會根據目標 OS/ABI 與 CPU 特性產生機器碼;不同平台的呼叫約定、可用指令與最佳化成熟度不同。流程:IL → JIT 編譯 → 機器碼執行。核心組件:CoreCLR JIT、平台 ABI、指令集。CPU Bound 工作對編譯品質高度敏感,造成本文中 Windows 家族的優勢。
- 難度: 高級
- 學習階段: 進階
- 關聯概念: A-Q18, A-Q14, B-Q12
B-Q12: CPU Bound 工作的主要瓶頸有哪些?
- A簡: 指令排程、快取命中、分支預測與記憶體頻寬,皆會影響。
- A詳: 原理說明:純運算負載受限於指令級平行度、管線停滯、快取命中、分支預測與大數運算帶來的記憶體存取。流程:取指→解碼→執行→寫回,任一階段停滯都降速。核心組件:CPU 快取、分支預測器、ALU/FPU。良好編譯器與資料區域性有助於緩解瓶頸。
- 難度: 高級
- 學習階段: 進階
- 關聯概念: B-Q11, B-Q10, D-Q8
B-Q13: 多執行緒、Producer/Consumer、Pipeline 模式差異?
- A簡: 控制顆粒與應用場景不同;本文採 Task/ThreadPool 預設排程。
- A詳: 原理說明:多執行緒是最基本的並行;Producer/Consumer 透過佇列解耦生產與處理;Pipeline 將工作分成階段串流。流程:模式決定工作切分與同步方式。核心組件:佇列、鎖、同步原語。本文刻意不強加模式,讓預設的 Task/ThreadPool 反映平台排程本質。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q3, A-Q4, C-Q2
B-Q14: 為何選擇 1/2/4/8 核心做伸縮測試?
- A簡: 對應常見實體核心數,觀察線性擴展與超執行緒邊際效益。
- A詳: 原理說明:核心數是平行最大度的上限。以 1/2/4/8 組合能觀察單核序列、雙核增益、四核主流伺服器、以及八執行緒(含 HT)的效益。流程:同負載跨核心數重測 → 對比三指標趨勢。核心組件:vCPU 配置、OS 調度器、ThreadPool 併發控制。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q12, A-Q9, B-Q19
B-Q15: 任務數與核心數比值如何影響測試?
- A簡: 任務≤核心時總時間平坦;任務≫核心時切換開銷上升。
- A詳: 原理說明:理想情況任務數接近核心數可最大化利用且維持低切換。任務數遠大於核心數,排程與快取失效率升高,平均時間變差。流程:設定不同任務數 → 比較總/平均時間與效率。核心組件:ThreadPool、OS 調度器、CPU 快取。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: B-Q9, A-Q6, D-Q2
B-Q16: 測試計時常用方法與注意事項?
- A簡: 使用高解析度計時(如 Stopwatch),避開時間源變動與暖機期。
- A詳: 原理說明:Stopwatch 通常基於高精度硬體計時器。流程:開測前暖機(JIT/快取)、統一計時點、收集每任務耗時與總跨度。核心組件:Stopwatch、GC 模式、時間源。注意避免跨時區/時間同步影響,並進行多次迭代取平均。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: D-Q1, D-Q5, C-Q8
B-Q17: 為何平均時間能反映 ThreadPool 行為?
- A簡: 平均時間受併發控制與排程公平影響,能揭示過度併發跡象。
- A詳: 原理說明:ThreadPool 將壓抑過度併發,平均時間不會隨任務數線性惡化;若平均時間顯著變差,可能表示切換過多或資源競爭。流程:比較不同任務數下平均時間曲線。核心組件:ThreadPool 動態調整、工作佇列負載。本文觀察曲線趨緩,顯示控制有效。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q6, B-Q2, D-Q6
B-Q18: 為何 Windows Server 2016 多核表現特別突出?
- A簡: 實測顯示最佳,可能受 OS 與執行階段最佳化綜合作用。
- A詳: 原理說明:雖屬預覽版本,但實測在 4/8 核心下領先。流程:相同 VM 規格 → 相同負載 → 三指標比較。核心組件:Windows 調度器、CoreCLR 在該平台的最佳化、Nano/Container 精簡化。具體細節未公開,但結果顯示多層最佳化帶來綜效。
- 難度: 高級
- 學習階段: 進階
- 關聯概念: A-Q14, A-Q15, B-Q3
B-Q19: 為何多核效益趨近線性但終會飽和(安瑟定律)?
- A簡: 可平行部分受限,串行部分與共享資源造成上限。
- A詳: 原理說明:Amdahl 定律指出總加速受限於不可平行部分比例;此外,鎖、記憶體頻寬、快取一致性與切換也會限制線性擴展。流程:提升核心數 → 觀察效率提升率遞減。核心組件:串行比例、共享資源、OS 調度。本文中 4→8 執行緒增益明顯低於 2→4 核的比例增益。
- 難度: 高級
- 學習階段: 進階
- 關聯概念: A-Q9, A-Q10, B-Q15
B-Q20: 為何本文避免手動控制執行緒與模式?
- A簡: 以預設 Task/ThreadPool 反映平台本質,避免實作偏誤。
- A詳: 原理說明:手動多執行緒、特定模式(Producer/Consumer、Pipeline)會引入策略差異,掩蓋平台差距。流程:使用 Task 預設行為 → 測量三指標。核心組件:Task、ThreadPool、OS 調度。此設計讓比較更聚焦於平台與執行階段的影響。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q3, B-Q1, B-Q13
Q&A 類別 C: 實作應用類
C-Q1: 如何用 .NET Core 建立 CPU Bound 測試專案?
- A簡: 建立 Console 專案,實作圓周率計算,加入計時與多任務執行。
- A詳: 步驟:1) dotnet new console 建專案。2) 編寫計算函式(純計算、少配置)。3) 用 Stopwatch 計總/單任務時間。程式碼片段:以 Task.Run 包裝計算,收集每任務耗時。注意:預熱一次 JIT、固定參數、防止 I/O 影響,使用 Release + x64。最佳實踐:重複多輪取平均,記錄環境資訊(OS、核心數、版本)。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: C-Q2, B-Q16, A-Q2
C-Q2: 如何用 Task 並行計算多次並量測三指標?
- A簡: 建立 N 個 Task 並行執行,量測總時間、個別時間與效率率。
- A詳: 步驟:1) 先單任務跑一次得 base。2) 建立 N 個 Task,Task.Run(() => Measure(Func))。3) Stopwatch 記錄總跨度。4) 計算平均時間與效率率。程式碼片段:使用 List<Task
>,await Task.WhenAll。注意:避免在 Task 內做 I/O、Console 輸出,防止干擾。最佳實踐:控制最大併發(預設 ThreadPool 足矣)。 - 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q5, A-Q7, B-Q1
C-Q3: 如何在 Windows Server 2012 R2 執行測試?
- A簡: 安裝 .NET Core 執行環境,編譯為 Release x64,命令列執行。
- A詳: 步驟:1) 安裝 .NET Runtime/SDK。2) dotnet restore/build -c Release -r win-x64。3) 設定電源計畫為高效能,關閉不必要服務。4) 執行:dotnet run -c Release 或執行輸出 EXE。注意:使用固定 CPU 核心數的 VM。最佳實踐:確保環境空閒、記錄版本與組態。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q11, C-Q7, B-Q7
C-Q4: 如何在 Windows Server 2016 Nano + Windows Container 執行?
- A簡: 於容器映像安裝 .NET,掛載程式碼,容器內建置與執行測試。
- A詳: 步驟:1) 準備 Windows 容器(Nano/Server Core)。2) 取得 .NET 容器映像(如 microsoft/dotnet)。3) docker run -v C:\app:C:\app -w C:\app microsoft/dotnet dotnet run -c Release。注意:對齊宿主與容器位元數、確認容器 CPU 配額。最佳實踐:以相同映像多次重複,保持層一致。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q15, A-Q16, B-Q8
C-Q5: 如何在 Ubuntu + Docker 重現測試?
- A簡: 安裝 Docker,使用 microsoft/dotnet 映像,掛載專案並執行。
- A詳: 步驟:1) apt 安裝 docker,啟動服務。2) docker pull microsoft/dotnet。3) docker run –rm -v $(pwd):/app -w /app microsoft/dotnet dotnet run -c Release。注意:避免 bind mount 到慢速檔案系統、確認容器未限 CPU。最佳實踐:固定映像版本、比對宿主/容器核心數。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q16, B-Q8, D-Q4
C-Q6: 如何在 Boot2Docker 執行測試?
- A簡: 啟動 docker-machine,設定環境,於容器內執行 dotnet 專案。
- A詳: 步驟:1) docker-machine start default。2) eval “$(docker-machine env default)”。3) docker run 指令同 C-Q5。注意:檔案共享效能較低,建議將專案複製到 VM 內部磁碟再執行。最佳實踐:避免大量 I/O,專注 CPU 測試。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q17, B-Q8, D-Q4
C-Q7: 如何在 VM 中調整核心數進行測試?
- A簡: 於 Hyper-V/VMware 設定虛擬處理器數,固定其他資源參數。
- A詳: 步驟:1) 關機 VM。2) 於管理工具設定 vCPU 為 1/2/4/8。3) 取消動態記憶體、固定儲存規格。4) 啟動並執行測試。注意:避免主機過載、確保電源計畫固定。最佳實踐:每個核心數重複多次,取平均。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q12, B-Q7, D-Q1
C-Q8: 如何計算並輸出三個指標(Total/Average/Efficiency)?
- A簡: 量測總跨度、收集任務耗時,套用效率率公式輸出報表。
- A詳: 步驟:1) base = 單任務總時間。2) N 任務:記錄 start、Stopwatch,完成收集每任務 elapsed。3) total = 總跨度;average = 均值;eff = ((total-base)N)/total100。程式碼:以 List
保存毫秒,最後序列化成 CSV。注意:避免 Console 大量輸出干擾。最佳實踐:封裝測量邏輯,確保重現性。 - 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q5, A-Q7, B-Q16
C-Q9: 如何調整 ThreadPool 以觀察影響?
- A簡: 設定最小/最大執行緒,或使用 LongRunning 任務專用執行緒。
- A詳: 步驟:1) ThreadPool.SetMinThreads(w,i/o)。2) 若需專用執行緒:TaskCreationOptions.LongRunning。3) 比較總/平均時間差異。程式碼:ThreadPool.Get/SetMinThreads 查詢與調整。注意:過度提高會導致切換開銷上升。最佳實踐:僅作探勘,正式測試以預設為準。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: B-Q2, D-Q6, B-Q17
C-Q10: 如何將測試數據視覺化比較平台差異?
- A簡: 匯出 CSV,於 Excel/繪圖工具製作三指標曲線與長柱圖。
- A詳: 步驟:1) 將每輪測試輸出 CSV:平台、核心數、任務數、三指標。2) 以 Total/Avg/Eff 分別繪製核心數×任務數之圖。3) 強調關鍵情境(如 64 任務)長柱比較。注意:標註環境版本與硬體配置。最佳實踐:同圖呈現多平台,便於交叉觀察趨勢。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q14, B-Q6, C-Q8
Q&A 類別 D: 問題解決類
D-Q1: 測試結果波動大怎麼辦?
- A簡: 控制背景負載、固定電源計畫、多輪迭代取平均與剔除離群值。
- A詳: 症狀:同環境多次測得時間差異大。原因:背景程序、溫度降頻、VM 爭用、計時器抖動。解決:關閉不必要服務、設定高效能電源、測前預熱、每組至少重複 5-10 次取平均。預防:記錄環境版本與主機負載,於空閒時段執行。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: B-Q7, B-Q16, C-Q7
D-Q2: 多核心下效率提升率偏低的原因?
- A簡: 過度併發、任務不均、快取失效率與 ThreadPool 調整不足。
- A詳: 症狀:核心數增加,Efficiency Rate 提升有限。原因:任務數遠超核心、資料區域性差、ThreadPool 最小執行緒過低、容器/VM CPU 配額。解決:任務數接近核心數、調整 SetMinThreads(謹慎)、檢查容器/VM 限制。預防:以 1/2/4/8 核與 1/2/4/8 任務做梯度測試找最佳點。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: B-Q15, B-Q9, C-Q9
D-Q3: 為何 1 核平行反而更慢?如何處理?
- A簡: 排程與切換開銷抵銷效益,改用序列或降低任務數。
- A詳: 症狀:1 核時任務加倍,總時間近線性增加甚至更差。原因:無並行,僅增加 Task/ThreadPool 與同步開銷。解決:1 核下改序列執行或單任務;必要時啟用較大顆粒度任務。預防:先以 1 核建基準,再決定是否平行化。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: A-Q13, B-Q1, B-Q6
D-Q4: 容器內 CPU 利用率不高或被限制怎麼辦?
- A簡: 檢查 CPU 配額/親和設定,使用 –cpus 或 cpuset 調整資源。
- A詳: 症狀:容器內 CPU 無法達到預期使用率。原因:cgroups 限制(shares、quota)、親和設定、宿主負載高。解決:docker run –cpus=N 或 –cpuset-cpus= 指定;確保宿主空閒。預防:統一定義容器資源限制,記錄在測試報表中。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: B-Q8, C-Q5, C-Q6
D-Q5: VM 中計時不準或漂移如何處理?
- A簡: 使用 Stopwatch、高精度計時,避免跨 VM/主機時間同步干擾。
- A詳: 症狀:相同測試時間統計異常。原因:虛擬時鐘精度差、時間同步跳動。解決:使用 Stopwatch 作相對時間;避免依賴系統時鐘差值;關閉不必要時間同步;升級 Hypervisor。預防:單一 VM 重複測,避免跨 VM 混測。
- 難度: 高級
- 學習階段: 進階
- 關聯概念: B-Q7, B-Q16, D-Q1
D-Q6: ThreadPool 飽和或排程延遲怎麼辦?
- A簡: 適度提高最小執行緒、避免小顆粒任務、必要時用 LongRunning。
- A詳: 症狀:任務等候時間長,平均時間飆升。原因:工作積壓、最小執行緒過低、小顆粒任務導致開銷。解決:ThreadPool.SetMinThreads 增量測;合併任務增大顆粒;長任務以 LongRunning 專用執行緒。預防:以預設為準,除非確診瓶頸再調整。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: B-Q2, C-Q9, B-Q17
D-Q7: 超執行緒效益不如預期如何診斷?
- A簡: 確認實體核心與執行緒數、工作性質,調整任務數與親和。
- A詳: 症狀:8 執行緒增益低於 4 核倍數。原因:HT 非等同核心加倍,算術飽和工作增益有限。解決:任務數以實體核心為主,必要時設定親和關係限制在實體核心。預防:評估負載特性,別盲目將任務數等同邏輯執行緒數。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: A-Q10, B-Q10, B-Q19
D-Q8: GC 影響 CPU Bound 測試怎麼減輕?
- A簡: 減少配置、重用物件、預熱 JIT,避免在熱路徑造成 GC 暫停。
- A詳: 症狀:偶發長尾延遲或時間抖動。原因:不必要配置引發 GC。解決:重用緩衝區、避免字串拼接 I/O、預熱一次;使用 Release、Server GC(視情況)。預防:設計純計算函式,將 I/O/配置移出熱路徑。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: B-Q12, C-Q1, C-Q2
D-Q9: 跨平台結果差距過大如何查因?
- A簡: 對齊 .NET 版本、Build 設定、容器映像與硬體配置再重測。
- A詳: 症狀:一平台顯著慢於預期。原因:不同 Runtime/SDK、Debug 模式、容器映像版本、CPU 頻率/電源策略。解決:統一版本與建置(Release x64)、固定映像 Tag、檢查電源/CPU 限制。預防:測前列出環境矩陣,確保可重現。
- 難度: 初級
- 學習階段: 基礎
- 關聯概念: C-Q3, C-Q5, B-Q11
D-Q10: 測試時 CPU 使用率未滿如何處理?
- A簡: 檢查任務數、ThreadPool 限制、容器/VM 配額與背景負載。
- A詳: 症狀:CPU 使用率顯著低於 100%。原因:任務不足、ThreadPool 未擴張、cgroups 限制、主機爭用。解決:增加任務至接近核心數、適調 SetMinThreads、取消 CPU 配額、於空閒主機測。預防:以小步增加任務觀察曲線,避免過度併發。
- 難度: 中級
- 學習階段: 核心
- 關聯概念: B-Q2, D-Q4, C-Q9
學習路徑索引
- 初學者:建議先學習哪 15 題
- A-Q1: 什麼是 CPU Bound 運算?
- A-Q2: 為何以計算圓周率測試 .NET Core 跨平台效能?
- A-Q3: .NET 的 Task 是什麼?和執行緒有何關係?
- A-Q4: Task 與 Thread 有何差異?
- A-Q5: 什麼是 Total Execute Time(總執行時間)?
- A-Q6: 什麼是 Average Execute Time(平均執行時間)?
- A-Q7: 什麼是 Efficiency Rate(效率提升率)?如何計算?
- A-Q8: 為何用效率提升率衡量平行處理?
- A-Q9: 平行處理與多核心的關係為何?
- A-Q12: 為何用 VM 控制硬體資源(1/2/4/8 核)?
- C-Q1: 如何用 .NET Core 建立 CPU Bound 測試專案?
- C-Q2: 如何用 Task 並行計算多次並量測三指標?
- C-Q8: 如何計算並輸出三個指標(Total/Average/Efficiency)?
- D-Q1: 測試結果波動大怎麼辦?
- D-Q3: 為何 1 核平行反而更慢?如何處理?
- 中級者:建議學習哪 20 題
- B-Q1: .NET 的 Task 調度如何運作?
- B-Q2: ThreadPool 如何控制執行緒數量?
- B-Q6: 總時間與平均時間的數學關係與意義?
- B-Q5: 效率提升率公式如何推導與使用?
- A-Q10: 超執行緒(Hyper-Threading)對效能有何影響?
- B-Q10: 超執行緒(HT)的硬體原理與限制?
- A-Q16: 容器(Docker)與原生執行的差異?
- B-Q8: 容器對 CPU 執行的影響機制?
- C-Q5: 如何在 Ubuntu + Docker 重現測試?
- C-Q6: 如何在 Boot2Docker 執行測試?
- C-Q7: 如何在 VM 中調整核心數進行測試?
- D-Q2: 多核心下效率提升率偏低的原因?
- D-Q4: 容器內 CPU 利用率不高或被限制怎麼辦?
- D-Q6: ThreadPool 飽和或排程延遲怎麼辦?
- D-Q7: 超執行緒效益不如預期如何診斷?
- B-Q15: 任務數與核心數比值如何影響測試?
- B-Q17: 為何平均時間能反映 ThreadPool 行為?
- C-Q9: 如何調整 ThreadPool 以觀察影響?
- C-Q10: 如何將測試數據視覺化比較平台差異?
- D-Q10: 測試時 CPU 使用率未滿如何處理?
- 高級者:建議關注哪 15 題
- B-Q3: .NET Core 在 Windows 與 Linux 的執行緒/排程差異?
- B-Q7: 虛擬化如何影響 CPU 排程與計時?
- B-Q11: JIT 在跨平台下可能出現的差異?
- B-Q12: CPU Bound 工作的主要瓶頸有哪些?
- B-Q18: 為何 Windows Server 2016 多核表現特別突出?
- B-Q19: 為何多核效益趨近線性但終會飽和(安瑟定律)?
- A-Q14: .NET Core 在 Windows 與 Linux 的效能差異總結?
- A-Q15: Nano Server 與 Server Core 有何差異與意義?
- D-Q5: VM 中計時不準或漂移如何處理?
- D-Q8: GC 影響 CPU Bound 測試怎麼減輕?
- C-Q4: 如何在 Windows Server 2016 Nano + Windows Container 執行?
- C-Q3: 如何在 Windows Server 2012 R2 執行測試?
- A-Q17: 為何 Boot2Docker 在 1 核表現最佳?
- A-Q18: JIT/原生編譯對 CPU Bound 測試影響?
- A-Q20: 選擇部署平台除了效能還該考量什麼?