在歷經千辛萬苦,經過各類性能分析方法,終於找到引起性能問題的瓶頸後,是否是馬上就要開始優化了呢?別急,動手以前,你能夠先看看下面這三個問題。緩存
首先,既然要作性能優化,那要怎麼判斷它是否是有效呢?特別是優化後,到底能提高多少性能呢?性能優化
第二,性能問題一般不是獨立的,若是有多個性能問題同時發生,你應該先優化哪個呢?網絡
第三,提高性能的方法並非惟一的,當有多種方法能夠選擇時,你會選用哪種呢?是否是總選那個最大程度提高性能的方法就好了呢?併發
若是你能夠輕鬆回答這三個問題,那麼二話不說就能夠開始優化。ide
好比,在前面的不可中斷進程案例中,經過性能分析,咱們發現是由於一個進程的直接 I/O ,致使了 iowait 高達 90%。那是否是用「直接 I/O 換成緩存 I/O」的方法,就能夠當即優化了呢?工具
按照上面講的,你能夠先本身思考下那三點。若是不能肯定,咱們一塊兒來看看。性能
第一個問題,直接 I/O 換成緩存 I/O,能夠把 iowait 從 90% 降到接近 0,性能提高很明顯。測試
第二個問題,咱們沒有發現其餘性能問題,直接 I/O 是惟一的性能瓶頸,因此不用挑選優化對象。優化
第三個問題,緩存 I/O 是咱們目前用到的最簡單的優化方法,並且這樣優化並不會影響應用的功能。spa
好的,這三個問題很容易就能回答,因此當即優化沒有任何問題。
可是,不少現實狀況,並不像我舉的例子那麼簡單。性能評估可能有多重指標,性能問題可能會多個同時發生,並且,優化某一個指標的性能,可能又致使其餘指標性能的降低。
那麼,面對這種複雜的狀況,咱們該怎麼辦呢?
接下來,咱們就來深刻分析這三個問題。
首先,來看第一個問題,怎麼評估性能優化的效果。
咱們解決性能問題的目的,天然是想獲得一個性能提高的效果。爲了評估這個效果,咱們須要對系統的性能指標進行量化,而且要分別測試出優化前、後的性能指標,用先後指標的變化來對比呈現效果。我把這個方法叫作性能評估「三步走」。
肯定性能的量化指標。
測試優化前的性能指標。
測試優化後的性能指標。
先看第一步,性能的量化指標有不少,好比 CPU 使用率、應用程序的吞吐量、客戶端請求的延遲等,均可以評估性能。那咱們應該選擇什麼指標來評估呢?
個人建議是不要侷限在單一維度的指標上,你至少要從應用程序和系統資源這兩個維度,分別選擇不一樣的指標。好比,以 Web 應用爲例:
應用程序的維度,咱們能夠用吞吐量和請求延遲來評估應用程序的性能。
系統資源的維度,咱們能夠用 CPU 使用率來評估系統的 CPU 使用狀況。
之因此從這兩個不一樣維度選擇指標,主要是由於應用程序和系統資源這二者間相輔相成的關係。
好的應用程序是性能優化的最終目的和結果,系統優化老是爲應用程序服務的。因此,必需要使用應用程序的指標,來評估性能優化的總體效果。
系統資源的使用狀況是影響應用程序性能的根源。因此,須要用系統資源的指標,來觀察和分析瓶頸的來源。
至於接下來的兩個步驟,主要是爲了對比優化先後的性能,更直觀地呈現效果。若是你的第一步,是從兩個不一樣維度選擇了多個指標,那麼在性能測試時,你就須要得到這些指標的具體數值。
仍是以剛剛的 Web 應用爲例,對應上面提到的幾個指標,咱們能夠選擇 ab 等工具,測試 Web 應用的併發請求數和響應延遲。而測試的同時,還能夠用 vmstat、pidstat 等性能工具,觀察系統和進程的 CPU 使用率。這樣,咱們就同時得到了應用程序和系統資源這兩個維度的指標數值。
不過,在進行性能測試時,有兩個特別重要的地方你須要注意下。
第一,要避免性能測試工具干擾應用程序的性能。一般,對 Web 應用來講,性能測試工具跟目標應用程序要在不一樣的機器上運行。
好比,在以前的 Nginx 案例中,我每次都會強調要用兩臺虛擬機,其中一臺運行 Nginx 服務,而另外一臺運行模擬客戶端的工具,就是爲了不這個影響。
第二,避免外部環境的變化影響性能指標的評估。這要求優化前、後的應用程序,都運行在相同配置的機器上,而且它們的外部依賴也要徹底一致。
好比仍是拿 Nginx 來講,就能夠運行在同一臺機器上,並用相同參數的客戶端工具來進行性能測試。
再來看第二個問題,開篇詞裏咱們就說過,系統性能老是牽一髮而動全身,因此性能問題一般也不是獨立存在的。那當多個性能問題同時發生的時候,應該先去優化哪個呢?
在性能測試的領域,流傳很廣的一個說法是「二八原則」,也就是說 80% 的問題都是由 20% 的代碼致使的。只要找出這 20% 的位置,你就能夠優化 80% 的性能。因此,我想表達的是,並非全部的性能問題都值得優化。
個人建議是,動手優化以前先動腦,先把全部這些性能問題給分析一遍,找出最重要的、能夠最大程度提高性能的問題,從它開始優化。這樣的好處是,不只性能提高的收益最大,並且極可能其餘問題都不用優化,就已經知足了性能要求。
那關鍵就在於,怎麼判斷出哪一個性能問題最重要。這其實仍是咱們性能分析要解決的核心問題,只不過這裏要分析的對象,從原來的一個問題,變成了多個問題,思路其實仍是同樣的。
因此,你依然能夠用我前面講過的方法挨個分析,分別找出它們的瓶頸。分析完全部問題後,再按照因果等關係,排除掉有因果關聯的性能問題。最後,再對剩下的性能問題進行優化。
若是剩下的問題仍是好幾個,你就得分別進行性能測試了。比較不一樣的優化效果後,選擇能明顯提高性能的那個問題進行修復。這個過程一般會花費較多的時間,這裏,我推薦兩個能夠簡化這個過程的方法。
第一,若是發現是系統資源達到了瓶頸,好比 CPU 使用率達到了 100%,那麼首先優化的必定是系統資源使用問題。完成系統資源瓶頸的優化後,咱們纔要考慮其餘問題。
第二,針對不一樣類型的指標,首先去優化那些由瓶頸致使的,性能指標變化幅度最大的問題。好比產生瓶頸後,用戶 CPU 使用率升高了 10%,而系統 CPU 使用率卻升高了 50%,這個時候就應該首先優化系統 CPU 的使用。
接着來看第三個問題,當多種方法均可用時,應該選擇哪種呢?是否是最大提高性能的方法,必定最好呢?
通常狀況下,咱們固然想選能最大提高性能的方法,這其實也是性能優化的目標。
但要注意,現實狀況要考慮的因素卻沒那麼簡單。最直觀來講,性能優化並不是沒有成本。性能優化一般會帶來複雜度的提高,下降程序的可維護性,還可能在優化一個指標時,引起其餘指標的異常。也就是說,極可能你優化了一個指標,另外一個指標的性能卻變差了。
一個很典型的例子是我將在網絡部分講到的 DPDK(Data Plane Development Kit)。DPDK 是一種優化網絡處理速度的方法,它經過繞開內核網絡協議棧的方法,提高網絡的處理能力。
不過它有一個很典型的要求,就是要獨佔一個 CPU 以及必定數量的內存大頁,而且老是以 100% 的 CPU 使用率運行。因此,若是你的 CPU 核數不多,就有點得不償失了。
因此,在考慮選哪一個性能優化方法時,你要綜合多方面的因素。切記,不要想着「一步登天」,試圖一次性解決全部問題;也不要只會「拿來主義」,把其餘應用的優化方法原封不動拿來用,卻不通過任何思考和分析。