12 | 套路篇:CPU 性能优化的几个思路
生活随笔
收集整理的這篇文章主要介紹了
12 | 套路篇:CPU 性能优化的几个思路
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
上一節我們一起回顧了常見的 CPU 性能指標,梳理了核心的 CPU 性能觀測工具,最后還總結了快速分析 CPU 性能問題的思路。雖然 CPU 的性能指標很多,相應的性能分析工具也很多,但理解了各種指標的含義后,你就會發現它們其實都有一定的關聯。順著這些關系往下理解,你就會發現,掌握這些常用的瓶頸分析套路,其實并不難。在找到 CPU 的性能瓶頸后,下一步要做的就是優化了,也就是找出充分利用 CPU 的方法,以便完成更多的工作。今天,我就來說說,優化 CPU 性能問題的思路和注意事項。確定性能的量化指標。 測試優化前的性能指標。 測試優化后的性能指標。 先看第一步,性能的量化指標有很多,比如 CPU 使用率、應用程序的吞吐量、客戶端請求的延遲等,都可以評估性能。那我們應該選擇什么指標來評估呢?我的建議是不要局限在單一維度的指標上,你至少要從應用程序和系統資源這兩個維度,分別選擇不同的指標。比如,以 Web 應用為例:
性能優化方法論
在我們歷經千辛萬苦,通過各種性能分析方法,終于找到引發性能問題的瓶頸后,是不是立刻就要開始優化了呢?別急,動手之前,你可以先看看下面這三個問題。- 首先,既然要做性能優化,那要怎么判斷它是不是有效呢?特別是優化后,到底能提升多少性能呢?
- 第二,性能問題通常不是獨立的,如果有多個性能問題同時發生,你應該先優化哪一個呢?
- 第三,提升性能的方法并不是唯一的,當有多種方法可以選擇時,你會選用哪一種呢?是不是總選那個最大程度提升性能的方法就行了呢?
- 第一個問題,直接 I/O 換成緩存 I/O,可以把 iowait 從 90% 降到接近 0,性能提升很明顯。
- 第二個問題,我們沒有發現其他性能問題,直接 I/O 是唯一的性能瓶頸,所以不用挑選優化對象。
- 第三個問題,緩存 I/O 是我們目前用到的最簡單的優化方法,而且這樣優化并不會影響應用的功能。
怎么評估性能優化的效果?
首先,來看第一個問題,怎么評估性能優化的效果。我們解決性能問題的目的,自然是想得到一個性能提升的效果。為了評估這個效果,我們需要對系統的性能指標進行量化,并且要分別測試出優化前、后的性能指標,用前后指標的變化來對比呈現效果。我把這個方法叫做性能評估“三步走”。- 應用程序的維度,我們可以用吞吐量和請求延遲來評估應用程序的性能。
- 系統資源的維度,我們可以用 CPU 使用率來評估系統的 CPU 使用情況。
- 好的應用程序是性能優化的最終目的和結果,系統優化總是為應用程序服務的。所以,必須要使用應用程序的指標,來評估性能優化的整體效果。
- 系統資源的使用情況是影響應用程序性能的根源。所以,需要用系統資源的指標,來觀察和分析瓶頸的來源。
- 第一,要避免性能測試工具干擾應用程序的性能。通常,對 Web 應用來說,性能測試工具跟目標應用程序要在不同的機器上運行。
- 第二,避免外部環境的變化影響性能指標的評估。這要求優化前、后的應用程序,都運行在相同配置的機器上,并且它們的外部依賴也要完全一致。
多個性能問題同時存在,要怎么選擇?
再來看第二個問題,開篇詞里我們就說過,系統性能總是牽一發而動全身,所以性能問題通常也不是獨立存在的。那當多個性能問題同時發生的時候,應該先去優化哪一個呢?在性能測試的領域,流傳很廣的一個說法是“二八原則”,也就是說 80% 的問題都是由 20% 的代碼導致的。只要找出這 20% 的位置,你就可以優化 80% 的性能。所以,我想表達的是,并不是所有的性能問題都值得優化。我的建議是,動手優化之前先動腦,先把所有這些性能問題給分析一遍,找出最重要的、可以最大程度提升性能的問題,從它開始優化。這樣的好處是,不僅性能提升的收益最大,而且很可能其他問題都不用優化,就已經滿足了性能要求。那關鍵就在于,怎么判斷出哪個性能問題最重要。這其實還是我們性能分析要解決的核心問題,只不過這里要分析的對象,從原來的一個問題,變成了多個問題,思路其實還是一樣的。所以,你依然可以用我前面講過的方法挨個分析,分別找出它們的瓶頸。分析完所有問題后,再按照因果等關系,排除掉有因果關聯的性能問題。最后,再對剩下的性能問題進行優化。如果剩下的問題還是好幾個,你就得分別進行性能測試了。比較不同的優化效果后,選擇能明顯提升性能的那個問題進行修復。這個過程通常會花費較多的時間,這里,我推薦兩個可以簡化這個過程的方法。- 第一,如果發現是系統資源達到了瓶頸,比如 CPU 使用率達到了 100%,那么首先優化的一定是系統資源使用問題。完成系統資源瓶頸的優化后,我們才要考慮其他問題。
- 第二,針對不同類型的指標,首先去優化那些由瓶頸導致的,性能指標變化幅度最大的問題。比如產生瓶頸后,用戶 CPU 使用率升高了 10%,而系統 CPU 使用率卻升高了 50%,這個時候就應該首先優化系統 CPU 的使用。
有多種優化方法時,要如何選擇?
接著來看第三個問題,當多種方法都可用時,應該選擇哪一種呢?是不是最大提升性能的方法,一定最好呢?一般情況下,我們當然想選能最大提升性能的方法,這其實也是性能優化的目標。但要注意,現實情況要考慮的因素卻沒那么簡單。最直觀來說,性能優化并非沒有成本。性能優化通常會帶來復雜度的提升,降低程序的可維護性,還可能在優化一個指標時,引發其他指標的異常。也就是說,很可能你優化了一個指標,另一個指標的性能卻變差了。一個很典型的例子是我將在網絡部分講到的 DPDK(Data Plane Development Kit)。DPDK 是一種優化網絡處理速度的方法,它通過繞開內核網絡協議棧的方法,提升網絡的處理能力。不過它有一個很典型的要求,就是要獨占一個 CPU 以及一定數量的內存大頁,并且總是以 100% 的 CPU 使用率運行。所以,如果你的 CPU 核數很少,就有點得不償失了。所以,在考慮選哪個性能優化方法時,你要綜合多方面的因素。切記,不要想著“一步登天”,試圖一次性解決所有問題;也不要只會“拿來主義”,把其他應用的優化方法原封不動拿來用,卻不經過任何思考和分析。CPU 優化
清楚了性能優化最基本的三個問題后,我們接下來從應用程序和系統的角度,分別來看看如何才能降低 CPU 使用率,提高 CPU 的并行處理能力。應用程序優化
首先,從應用程序的角度來說,降低 CPU 使用率的最好方法當然是,排除所有不必要的工作,只保留最核心的邏輯。比如減少循環的層次、減少遞歸、減少動態內存分配等等。除此之外,應用程序的性能優化也包括很多種方法,我在這里列出了最常見的幾種,你可以記下來。- 編譯器優化:很多編譯器都會提供優化選項,適當開啟它們,在編譯階段你就可以獲得編譯器的幫助,來提升性能。比如, gcc 就提供了優化選項 -O2,開啟后會自動對應用程序的代碼進行優化。
- 算法優化:使用復雜度更低的算法,可以顯著加快處理速度。比如,在數據比較大的情況下,可以用 O(nlogn) 的排序算法(如快排、歸并排序等),代替 O(n^2) 的排序算法(如冒泡、插入排序等)。
- 異步處理:使用異步處理,可以避免程序因為等待某個資源而一直阻塞,從而提升程序的并發處理能力。比如,把輪詢替換為事件通知,就可以避免輪詢耗費 CPU 的問題。
- 多線程代替多進程:前面講過,相對于進程的上下文切換,線程的上下文切換并不切換進程地址空間,因此可以降低上下文切換的成本。
- 善用緩存:經常訪問的數據或者計算過程中的步驟,可以放到內存中緩存起來,這樣在下次用時就能直接從內存中獲取,加快程序的處理速度。
系統優化
從系統的角度來說,優化 CPU 的運行,一方面要充分利用 CPU 緩存的本地性,加速緩存訪問;另一方面,就是要控制進程的 CPU 使用情況,減少進程間的相互影響。具體來說,系統層面的 CPU 優化方法也有不少,這里我同樣列舉了最常見的一些方法,方便你記憶和使用。- CPU 綁定:把進程綁定到一個或者多個 CPU 上,可以提高 CPU 緩存的命中率,減少跨 CPU 調度帶來的上下文切換問題。
- CPU 獨占:跟 CPU 綁定類似,進一步將 CPU 分組,并通過 CPU 親和性機制為其分配進程。這樣,這些 CPU 就由指定的進程獨占,換句話說,不允許其他進程再來使用這些 CPU。
- 優先級調整:使用 nice 調整進程的優先級,正值調低優先級,負值調高優先級。優先級的數值含義前面我們提到過,忘了的話及時復習一下。在這里,適當降低非核心應用的優先級,增高核心應用的優先級,可以確保核心應用得到優先處理。
- 為進程設置資源限制:使用 Linux cgroups 來設置進程的 CPU 使用上限,可以防止由于某個應用自身的問題,而耗盡系統資源。
- NUMA(Non-Uniform Memory Access)優化:支持 NUMA 的處理器會被劃分為多個 node,每個 node 都有自己的本地內存空間。NUMA 優化,其實就是讓 CPU 盡可能只訪問本地內存。
- 中斷負載均衡:無論是軟中斷還是硬中斷,它們的中斷處理程序都可能會耗費大量的 CPU。開啟 irqbalance 服務或者配置 smp_affinity,就可以把中斷處理過程自動負載均衡到多個 CPU 上。
千萬避免過早優化
掌握上面這些優化方法后,我估計,很多人即使沒發現性能瓶頸,也會忍不住把各種各樣的優化方法帶到實際的開發中。不過,我想你一定聽說過高德納的這句名言, “過早優化是萬惡之源”,我也非常贊同這一點,過早優化不可取。因為,一方面,優化會帶來復雜性的提升,降低可維護性;另一方面,需求不是一成不變的。針對當前情況進行的優化,很可能并不適應快速變化的新需求。這樣,在新需求出現時,這些復雜的優化,反而可能阻礙新功能的開發。所以,性能優化最好是逐步完善,動態進行,不追求一步到位,而要首先保證能滿足當前的性能要求。當發現性能不滿足要求或者出現性能瓶頸時,再根據性能評估的結果,選擇最重要的性能問題進行優化。總結今天,我帶你梳理了常見的 CPU 性能優化思路和優化方法。發現性能問題后,不要急于動手優化,而要先找出最重要的、可以獲得最大性能提升的問題,然后再從應用程序和系統兩個方面入手優化。這樣不僅可以獲得最大的性能提升,而且很可能不需要優化其他問題,就已經滿足了性能要求。但是記住,一定要忍住“把 CPU 性能優化到極致”的沖動,因為 CPU 并不是唯一的性能因素。在后續的文章中,我還會介紹更多的性能問題,比如內存、網絡、I/O 甚至是架構設計的問題。如果不做全方位的分析和測試,只是單純地把某個指標提升到極致,并不一定能帶來整體的收益。思考由于篇幅的限制,我在這里只列舉了幾個最常見的 CPU 性能優化方法。除了這些,還有很多其他應用程序,或者系統資源角度的性能優化方法。我想請你一起來聊聊,你還知道哪些其他優化方法呢?CPU性能優化思路方法論1.性能優化的效果判斷三步走理論(1)確定性能的量化指標-一般從應用程序緯度和系統資源緯度分析(2)測試優化前的性能指標(3)測試性能優化后的性能指標2.當性能問題有多個時,優先級問題先優化最重要的且最大程度提升性能的問題開始優化3.優化方法有多個時,該如何選綜合多方面因素CPU優化應用程序優化:排除不必要工作,只留核心邏輯1.減少循環次數 減少遞歸 減少動態沒錯分配2.編譯器優化3.算法優化4.異步處理5.多線程代替多進程6.緩存系統優化:利用CPU緩存本地性,加速緩存訪問;控制進程的cpu使用情況,減少程序的處理速度1.CPU綁定2.CPU獨占3.優先級調整4.為進程設置資源限制5.NUMA優化6.中斷負載均衡很重要的一點:切記過早優化總結
以上是生活随笔為你收集整理的12 | 套路篇:CPU 性能优化的几个思路的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 11 | 套路篇:如何迅速分析出系统CP
- 下一篇: 13 | 答疑(一):无法模拟出 RES