# Day 3 性能工程基本定律

## Pareto Principle

`Pareto Principle` 又被稱為 `80/20` 法則、`關鍵少數`法則。在很多場景下，大約 20% 的因素操控著 80% 的局面。也就是說，所有的變數中，比較重要的通常只有 20%，是所謂的`關鍵少數`。其餘 80% 的因素則相對次要。

在軟體產業中，這一法則同樣適用，且能帶來顯著的效率提升。以下是幾個應用場景及其具體意義：

| 應用場景 | 套用法則 | 具體意義 |
| --- | --- | --- |
| 應用程式的使用 | 80% 的使用者使用集中在大約 20% 的功能模組 | 首先對經常使用的模組進行充分的優化，提升整體使用體驗。 |
| 程式碼開發時間的分配 | 80% 的開發時間往往花費在最常用的 20% 程式碼上 | 需要合理有序地規劃開發時間，聚焦在最重要的程式碼部分。 |
| 程式碼的維護 | 80% 的程式碼演進與改動集中在大約 20% 的程式碼上 | 熟悉並重點維護經常變動的程式碼，以提高開發效率。 |
| 技術債管理 | 80% 的技術債集中在大約 20% 的系統模塊上 | 應優先解決這些技術債重點，降低系統風險。 |
| 程式碼的修正與糾錯 | 80% 的錯誤發生在大約 20% 的程式碼上 | 在修復 Bug 時，應重點關注那些最容易產生問題的程式碼段。 |
| 使用者流量的時間分佈 | 80% 的流量集中在總時間段的特定 20% 內 | 在設計與部署應用程式時，應充分考慮使用者訪問的高峰期及其影響。 |
| 程式碼的優化 | 80% 的應用程式運行時間集中在大約 20% 的程式碼上 | 找出關鍵的程式碼並進行針對性優化，以顯著提升應用效能。 |
| 性能瓶頸分析 | 80% 的性能瓶頸來自大約 20% 的程式碼或資源 | 集中資源優化這些瓶頸所在，以取得顯著性能提升。 |
| DevOps 流程自動化 | 80% 的手動操作集中在大約 20% 的重複性任務上 | 應優先對這些重複性任務進行自動化，以提高運維效率。 |
| 資料庫查詢優化 | 80% 的資料庫負載來自大約 20% 的查詢語句 | 對這些高負載查詢進行優化，能顯著改善資料庫性能。 |
| 安全漏洞修補 | 80% 的安全漏洞集中在大約 20% 的程式碼路徑或配置上 | 應優先檢查並修補這些容易暴露漏洞的程式碼區段或配置項。 |
| 使用者回饋處理 | 80% 的回饋問題來自大約 20% 的使用者 | 應優先處理這些使用者的回饋，因為它們往往反映了最普遍的問題。 |

這些場景進一步擴展了 Pareto Principle 的應用範疇，使得法則在軟體開發的各個層面都能發揮其影響力。通過識別和優先處理這些「關鍵少數」，可以在資源有限的情況下，取得最大化的效率和效果。

這一法則的核心價值在於：**先解決 20% 最關鍵的問題，便能達到 80% 的效果**。而剩餘 80% 的問題，即便投入大量資源，也只能獲得相對有限的改進。

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723733034540/f80b7771-276d-4730-9cb7-65c04ae505ac.jpeg align="center")

服務提供的各種功能中，只要跟**營收**或所謂的**核心競爭力**有直接影響關係的功能，肯定是關鍵部份，絕對是要關注相關問題來處理並持續優化的。

## Amdahl's Law

衡量 CPU 運行併發處理時總體性能的提昇度。

用個生活例子洗衣服與曬衣浮來說明，洗衣服與晒衣服都需要 10 分鐘才能完成，總時長需要 20 分鐘才能完成這件事。

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723742496510/d091d4bb-6bbc-467a-9fb0-ea3154d8c482.png align="center")

如果我們能把晒衣服給加快成 5 分鐘就能完成。晒衣服的速度就提昇了 2倍。總時長來到 15 分鐘。

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723742486387/c977f1c8-34cb-4ea8-855a-d6c67e7647df.png align="center")

這樣的思維繼續優化下去。都需要至少 10 分鐘才能完成這整件事情，是因為我們沒對洗衣服進行優化。所以整體加速比並不會高過 2 。

而根據 Amdahl's Law 描述，如果我們能使用多個 CPU 來平行處理以達到加速時，其實總時常還是受限於程式所需的串行時間百分比。比如一段處理邏輯其中的 50%只能串行，而其他一半可以平行，那麼最大的加速比就是 2，不會更高了，無論買再多顆 CPU 或多快都不會將加速比提高到大於 2。

如果在這種情況下，改善程式碼串行流程與邏輯的可能會比無腦使用多核心平行處理來的有用。

這裡提供公式能計算，如果整體執行時間長度是 1，其中要進行優化加速的功能模組運行時長是 P。如果對這模組的加速比是 N，那麼優化加速後的時間會是

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723744119637/2aa3ee8c-3c1e-4854-8ed4-6a9860af56b7.png align="center")

如果要與舊有線上運行的時間相比來算出加速比，公式如下

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1723744355102/1b1fde7b-ae09-4adc-9029-008de8ed0f84.png align="center")

所以 Amdahl's Law 主要是給我們方向，

1. 優先優化佔用時間最常的功能模組/流程，因為這樣可以最大限度的提昇加速比。
    
2. 針對一個性能優化的計畫，我們可以根據這樣的計算給出準確的效果預估和整體系統的性能預算。
    

![undefined](https://upload.wikimedia.org/wikipedia/commons/thumb/e/ea/AmdahlsLaw.svg/2560px-AmdahlsLaw.svg.png align="left")

上圖顯示的是 **Amdahl's Law** 的視覺化結果。它描述了在某種情況下，增加處理器數量對系統性能（加速比）的影響。

* **X軸** 代表處理器的數量，從 1 到 65536。
    
* **Y軸** 代表加速比（Speedup），即增加處理器數量後系統的性能提升程度。
    
* 圖中有四條不同的曲線，分別表示在不同的「可並行比例」（Parallel portion）下，隨著處理器數量增加所能達到的加速比：
    
    * **50%**（淺藍色實線）：當程序有 50% 可以並行執行時，隨著處理器數量的增加，加速比增加有限，並在處理器數量增加到一定程度後幾乎不再上升。
        
    * **75%**（紅色虛線）：當程序有 75% 可以並行執行時，加速比會比 50% 高，但依然會隨著處理器數量增加而趨於平緩。
        
    * **90%**（紫色點劃線）：當程序有 90% 可以並行執行時，加速效果更加明顯，但同樣隨著處理器數量的增加，最終加速比也會趨於飽和。
        
    * **95%**（綠色虛線）：當程序有 95% 可以並行執行時，加速比相對前面幾個比例更高，但最終也會達到極限。
        

能發現隨著可並行比例的提高（從 50% 到 95%），可以看到加速比有明顯的提升，但無論可並行比例多高，最終都會出現加速比飽和的現象，即增加更多的處理器已經無法帶來顯著的性能提升。

這個現象表明，即使是高度可平行的程序，在某一點之後，非平行部分（程序中無法平行的部分）會成為整個系統性能提升的瓶頸。

這張圖旨在說明 Amdahl's Law 的核心：即使增加處理器數量也有其效果的上限，這個上限受限於程序中無法並行的部分。

### 與 Profiling 的關聯：

Profiling 是一種技術，用來分析應用程式的性能瓶頸，找出哪部分程式碼消耗了最多的資源或時間。通過 Profiling，開發者可以更清楚地了解哪些部分是系統的「熱點」，即主要的串行瓶頸。這正是 Amdahl's Law 中需要優化的部分。 根據 Amdahl's Law，只有優化了這些佔用大量時間的部分，才能最大限度地提升系統的整體性能。因此，Profiling 給出了明確的優化方向：找到最需要改進的瓶頸程式碼部分進行優化，而不是盲目地增加硬體資源。

### 與 Observability 的關聯：

Observability 涵蓋了系統的可觀測性，包括 Logging、Tracing、Metrics 和 Profiling。Observability 允許我們在分佈式系統中跟蹤和分析系統的行為及其性能表現。 透過 Observability，我們可以在運行時精確地看到哪部分系統是串行的、哪部分是並行的，並且能夠對這些部分進行實時的監控和分析。這樣可以及時發現和修正可能的性能瓶頸，並驗證所做的優化是否真正有效。 同時，Observability 讓我們能夠在不同環境中觀察到 Amdahl's Law 所描述的現象，並提供足夠的數據來預測系統在不同硬體配置下的行為。

### 小結

Amdahl's Law 可以作為性能優化的理論基礎，指導開發者通過 Profiling 來找出最有效的優化點，而 Observability 提供了實施這些優化後的反饋回路，幫助驗證優化的成效。 在實際的系統中，藉由 Observability 和 Profiling，可以確保我們所做的每一個性能優化都是基於數據驅動的決策，並能夠在系統整體性能中看到顯著提升。 這樣的結合可以幫助你在性能優化和可觀測性建設中達到更好的效果，從而確保系統能夠在現有資源下達到最佳性能表現。

## Little's Law

Little's Law 是性能分析和基於排隊理論中的基本定律，適用於任何穩定的系統或流程中、非搶佔式（先來先服務，不能插隊）的系統中，該系統或流程存在進入、處理和離開三個基本環節。這個定律可以幫助我們理解系統中請求或客戶的平均數量、到達速率和平均等待時間之間的關係。

#### 適用條件
Little's Law 有幾個重要的前提條件：

- 穩定系統: 系統必須是穩定的，即長時間內進入系統的請求數量與離開系統的請求數量相等，否則L會無限增長。

- FIFO（先進先出）或其他服務策略: 雖然Little's Law不依賴於具體的服務策略，但在FIFO（先進先出）的策略下，W的計算更為簡單和直接。

- 平均值: Little's Law 基於長期平均值的概念，因此它描述的是在長期穩定狀態下的系統行為。

其內容為：在一個穩定的系統中，長期的平均使用者人數（L），等於長期的有效抵達率（λ），乘以顧客在這個系統中平均的等待時間（W）； 或者，我們可以用一個代數式來表達： L = λW

#### 參數解釋
- L (Average number of items in the system): 系統中的平均請求數量，也可以理解為在系統中同時存在的平均客戶數量。在計算機系統中，這可以表示為當前正在處理或等待處理的請求數。

- λ (Arrival rate): 系統的到達速率，即每單位時間內到達系統的請求數量（通常以每秒請求數，RPS，表示）。這表示系統中流入的客戶或請求的速率。

- W (Average time in the system): 請求在系統中的平均時間，這包括了從請求進入系統到離開系統的整個過程時間，包括排隊時間和實際處理時間。

是不是看不懂？換個角度就容易理解了。如下圖所示，使用者按照一定的速度持續地請求我們的系統，假設這個速度是每分鐘 λ 個使用者。每個使用者的請求在系統的平均處理時間是 W 分鐘。

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1724082384419/70fe74e2-fa87-4e5d-b29c-b79cd567cb1e.jpeg align="center")

按照這法則計算，如果系統處理速度恰好滿足使用者到速度的話，一方面系統就不會有空閒浪費，且使用者也不需要排隊在系統外等待。在這樣的穩定狀態下，我們系統的總容量恰好等於系統裡面正在處理的使用者請求數量。也就剛好 L = λW。

如果我們的系統面臨著使用者訪問速度是每秒鐘 1000 個使用者，每個使用者在我們服務花費的平均時間是 0.2 秒。那麼根據 little's law 我們的系統將容納 1000 * 0.2 = 200 個使用者請求。這益為著，在任何時間點，這個系統中平均有 200 個使用者的請求正在被處理或等待處理。但如果使用者的併發訪問速度增大到每分鐘 2000。在這種情況下，我們能應對的方法如下︰

1. 把使用者的處理時間減半，從 0.2 秒減半成 0.1 秒。這樣系統容量就保持不變。因為處理時間減半，但剛好可以應對訪問速率加倍的請求。系統容量等於 2000 * 0.1 = 200。

2. 擴大系統容量。維持處理時間不變還是 0.2 秒。但因為使用者訪問速度加倍了，所以系統容量也要加倍，變成 4000。假如本來的系統背後是5台主機，那麼現在就變成需要 10 台主機。

從這裡的討論就能看到 Little's Law 在優化工作中的兩種用途︰
1.  協助我們設計性能測試的環境。如果我們需要模擬一個固定容量的環境時，這法則能協助我們設定使用者請求速度與每個請求的處理時間。

2. 協助我們驗證測試結果的正確性。

Little's Law 為我們提供了一個強大的工具來理解系統中的平均請求數量、到達速率和平均等待時間之間的關係。這在設計和優化系統性能時非常有用，特別是當我們需要確保系統能夠承載預期的負載時。

然而，僅僅理解系統中的請求數量和等待時間還不足以完全掌握系統的性能狀況。我們還需要考慮系統資源的利用情況，特別是核心資源（如CPU、記憶體、I/O等）的使用情況。

這時候，Utilization Law 就成為我們分析系統性能的另一個關鍵工具。它專注於系統資源的利用率，幫助我們理解系統在不同負載下的行為。

## Utilization Law
Utilization Law 是計算機系統性能分析中的一個重要定律，用於描述系統資源的利用率。它表示系統中資源的繁忙程度，尤其是CPU、I/O設備或其他關鍵資源。當系統利用率 U 接近1時，這意味著系統的資源幾乎完全被占用，此時任何額外的負載都可能導致系統性能下降，甚至是崩潰。

公式與參數解釋
U=λS

- U (Utilization): 系統的利用率，是一個從0到1（或0%到100%）的數值，表示資源在時間範圍內的使用情況。U=1表示資源完全被佔用，U=0表示資源閒置。

- λ (Arrival rate): 與Little's Law中的λ相同，表示系統的到達速率（每秒請求數）。

- S (Service time): 每個請求的平均服務時間，即資源處理一個請求所需的時間。

適用條件
線性關係: Utilization Law假設服務時間和到達速率之間存在線性關係，這在大多數情況下是合理的。

資源單一性: Utilization Law通常應用於單個資源的利用率計算，而不適合直接用於分析多個資源的複合利用率。

理想化情境: 利用率通常在理想情境下計算，但實際情況可能更為複雜，包括資源的上下線時間、不同優先級的請求等。

應用範例
假設一個系統的處理能力是每秒100個請求（λ=100 RPS），每個請求的平均服務時間為0.02秒（S=0.02秒），則該系統的CPU利用率為：
𝑈 = 100 × 0.02 = 2

這表示系統的理論利用率為200%，但實際上，當利用率超過100%時，系統就會開始產生延遲或瓶頸，這表明系統處於超負荷狀態。

綜合應用與實例說明
在實際應用中，Little's Law 和 Utilization Law 可以結合使用來分析和優化系統性能。以下是一個綜合應用的例子：

綜合範例
假設一個在線支付系統，其到達速率（λ）為500 RPS，每個請求的平均服務時間（S）為0.005秒。利用Utilization Law，我們可以計算出系統的CPU利用率（U）：

𝑈 = 500 × 0.005 = 2.5

這意味著系統的利用率為250%，明顯超過了100%的合理上限，因此系統處於過載狀態，可能會導致處理延遲或請求排隊。

接著，我們利用Little's Law來分析系統中的平均請求數量和平均等待時間。如果我們觀察到系統中同時存在的請求數量（L）約為50，則可以計算平均等待時間（W）：
𝑊 =𝐿 / 𝜆  = 50 / 500 = 0.1秒

這意味著每個請求在系統中平均需要等待0.1秒來完成處理。如果這個等待時間超過了用戶的接受範圍，則需要考慮升級系統資源或優化服務流程。


### Little's Law 與 Utilization Law 的綜合應用
在實際應用中，Little's Law 和 Utilization Law 是相互補充的。Little's Law 幫助我們理解系統中請求的數量和等待時間，而 Utilization Law 則告訴我們資源的使用情況。

例如，當我們發現系統中的平均請求數量（L）大於預期時，我們可以通過檢查系統的利用率（U）來了解是否因為資源過度利用導致的等待時間增加。如果 U 接近或超過1，則表明系統資源已經達到了極限，這就需要我們考慮升級資源或優化處理流程來降低 S 或增加系統的處理能力。

當這兩個定律結合使用時，我們能夠全面地分析系統的性能，識別出哪些資源過度使用，哪些部分的處理時間過長，從而做出更明智的優化決策。這樣，我們可以在資源有限的情況下，通過調整系統資源和優化處理流程，最大限度地提升系統的效能，確保它在高負載下依然運行良好。

## 小結
總結來說，這三個重要的法則——Pareto Principle、Amdahl's Law 和 Little's Law——為我們提供了關於如何優化系統性能的不同視角。

Pareto Principle (80/20 法則) 強調了在軟體開發和性能優化中，應該聚焦於少數關鍵因素，因為這些因素往往決定了大部分的結果。通過專注於這些「關鍵少數」，我們能夠在資源有限的情況下取得最大的效率提升。

Amdahl's Law 提供了一個框架來理解系統性能的提升限制，特別是在並行處理的情境下。它提醒我們，無論我們增加多少資源，系統性能的提升最終受限於那些無法並行化的部分。因此，針對系統中串行部分的優化，比單純增加硬體資源更為重要。

Little's Law 則幫助我們量化系統中請求的處理情況，揭示了到達率、等待時間和系統中平均請求數量之間的關係。這對於設計和調整系統以應對不同的負載非常有用。

結合這三個法則，我們可以從不同的角度分析和優化系統性能：首先，應聚焦於最關鍵的問題（Pareto Principle）；其次，理解系統並行能力的局限（Amdahl's Law）；最後，確保系統能夠有效地處理請求並保持穩定（Little's Law）。這樣，我們就能制定出更加全面和有效的優化策略，讓系統在高負載下依然運行平穩，並且資源使用達到最佳化。

