性能優化第一課:性能指標

性能優化第一課:性能指標

如果要問目前最火熱的 JVM 知識是什麼? 很多同學的答案可能是 “JVM 調優” 或者 “JVM 性能優化”。但是具體需要從哪兒入手,怎麼去做呢?

其實“調優”是一個診斷和處理手段,我們最終的目標是讓系統的處理能力,也就是“性能”達到最優化,這個過程我們就像是一個醫生,診斷和治療“應用系統”這位病人。我們以作爲醫生給系統看病作爲對比,“性能優化”就是實現“把身體的大小毛病治好,身體達到最佳健康狀態”的目標。

那麼去醫院看病,醫生會是怎麼一個處理流程呢?先簡單的詢問和了解基本情況,發燒了沒有,咳嗽幾天了,最近吃了什麼,有沒有拉肚子一類的,然後給患者開了一系列的檢查化驗單子:去查個血、拍個胸透、驗個尿之類的。然後就會有醫生使用各項儀器工具,依次把去做這些項目的檢查,檢查的結果就是很多標準化的具體指標(這裏就是我們對 JVM 進行信息收集,變成各項指標)。

然後拿過來給醫生診斷用,醫生根據這些指標數據判斷哪些是異常的,哪些是正常的,這些異常指標說明了什麼問題(對系統問題進行分析排查),比如是白細胞增多(系統延遲和抖動增加,偶爾宕機),說明可能有炎症(比如 JVM 配置不合理)。最後要“對症下藥”,開出一些阿莫西林或者頭孢(對 JVM 配置進行調整),叮囑怎麼頻率,什麼時間點服藥,如果問題比較嚴重,是不是要住院做手術(系統重構和調整),同時告知一些注意事項(對日常運維的要求和建議),最後經過一段時間治療,逐漸好轉,最終痊癒(系統延遲降低,不在抖動,不再宕機)。通過了解 JVM 去讓我們具有分析和診斷能力,是本課程的核心主題。

1.1 量化性能相關指標

"沒有量化就沒有改進",所以我們需要先了解和度量性能指標,就像在醫院檢查以後得到的檢驗報告單一樣。因爲人的主觀感覺是不靠譜的,個人經驗本身也是無法複製的,而定義了量化的指標,就意味着我們有了一個客觀度量體系。哪怕我們最開始定義的指標不是特別精確,我們也可以在使用過程中,隨着真實的場景去驗證指標有效性,進而替換或者調整指標,逐漸的完善這個量化的指標體系,成爲一個可以複製和複用的有效工具。就像是上圖的血常規檢查報告單,一旦成爲這種標準化的指標,那麼使用它得到的結果,也就是這個報告單,給任何一個醫生看,都是有效的,一般也能得到一致的判斷結果。

那麼系統性能的診斷要做些什麼指標呢?我們先來考慮,進行要做診斷,那麼程序或 JVM 可能出現了問題,而我們排查程序運行中出現的問題,比如排查程序 BUG 的時候,要優先保證正確性,這時候就不僅僅是 JVM 本身的問題,例如死鎖等等,程序跑在 JVM 裏,現象出現在 JVM 上,很多時候還要深入分析業務代碼和邏輯確定 Java 程序哪裏有問題。

  1. 分析系統性能問題: 比如是不是達到了我們預期性能指標,判斷資源層面有沒有問題,JVM 層面有沒有問題,系統的關鍵處理流程有沒有問題,業務流程是否需要優化;

  2. 通過工具收集系統的狀態,日誌,包括打點做內部的指標收集,監控並得出關鍵性能指標數據,也包括進行壓測,得到一些相關的壓測數據和性能內部分析數據;

  3. 根據分析結果和性能指標,進行資源配置調整,並持續進行監控和分析,以優化性能,直到滿足系統要求,達到系統的最佳性能狀態。

計算機系統中,性能相關的資源主要分爲這幾類:

  • CPU:CPU 是系統最關鍵的計算資源,在單位時間內有限,也是比較容易由於業務邏輯處理不合理而出現瓶頸的地方,浪費了 CPU 資源和過渡消耗 CPU 資源都不是理想狀態,我們需要監控相關指標;

  • 內存:內存則對應程序運行時直接可使用的數據快速暫存空間,也是有限的,使用過程隨着時間的不斷的申請內存又釋放內存,好在 JVM 的 GC 幫我們處理了這些事情,但是如果 GC 配置的不合理,一樣會在一定的時間後,產生包括 OOM 宕機之類的各種問題,所以內存指標也需要關注;

  • IO(存儲+網絡):CPU 在內存中把業務邏輯計算以後,爲了長期保存,就必須通過磁盤存儲介質持久化,如果多機環境、分佈式部署、對外提供網絡服務能力,那麼很多功能還需要直接使用網絡,這兩塊的 IO 都會比 CPU 和內存速度更慢,所以也是我們關注的重點。

其他各種更細節的指標,將會在工具和命令的使用章節詳細介紹。

1.2 性能優化中常見的套路

性能優化一般要存在瓶頸問題,而瓶頸問題都遵循 80/20 原則。既我們把所有的整個處理過程中比較慢的因素都列一個清單,並按照對性能的影響排序,那麼前 20% 的瓶頸問題,至少會對性能的影響佔到 80% 比重。換句話說,我們優先解決了最重要的幾個問題,那麼性能就能好一大半。

我們一般先排查基礎資源是否成爲瓶頸。看資源夠不夠,只要成本允許,加配置可能是最快速的解決方案,還可能是最划算,最有效的解決方案。 與 JVM 有關的系統資源,主要是 CPU 和 內存 這兩部分。 如果發生資源告警/不足, 就需要評估系統容量,分析原因。

至於 GPU 、主板、芯片組之類的資源則不太好衡量,通用計算系統很少涉及。

一般衡量系統性能的維度有 3 個:

  • 延遲(Latency): 一般衡量的是響應時間(Response Time),比如平均響應時間。但是有時候響應時間抖動的特別厲害,也就是說有部分用戶的響應時間特別高,這時我們一般假設我們要保障 95% 的用戶在可接受的範圍內響應,從而提供絕大多數用戶具有良好的用戶體驗,這就是延遲的95線(P95,平均 100 個用戶請求中 95 個已經響應的時間),同理還有99線,最大響應時間等(95 線和 99 線比較常用;用戶訪問量大的時候,對網絡有任何抖動都可能會導致最大響應時間變得非常大,最大響應時間這個指標不可控,一般不用)。

  • 吞吐量(Throughput): 一般對於交易類的系統我們使用每秒處理的事務數(TPS)來衡量吞吐能力,對於查詢搜索類的系統我們也可以使用每秒處理的請求數(QPS)。

  • 系統容量(Capacity): 也叫做設計容量,可以理解爲硬件配置,成本約束。

這 3 個維度互相關聯,相互制約。只要系統架構允許,增加硬件配置一般都能提升性能指標。但隨着摩爾定律的失效,增加硬件配置到一定的程度並不能提供性能的線性擴展,比如說已經比較高配置的機器,CPU 核數或頻率、內存擴大一倍,一方面並不能帶來一倍的性能提升,另一方面帶來的成本不止一倍,性價比急速下降,而且到了一定程度想加都加不上去了。作爲雲廠商的領頭羊 AWS 今年纔開始嘗試提供 256 核的機器,而阿里雲目前最高支持 104 核。所以目前來說,整體上使用分佈式的解決辦法,以及局部上對每個系統進行分析調優,是性價比最高的選擇。

小知識,吞吐量越大的系統,是不是延遲就越低?

 

上面這個命題確實不成立,但是反過來一般成立。

延遲降低,吞吐肯定會上去。吞吐量大,延遲可能很低,也可能很高。

舉個我每次講課都講得例子。

從密雲水庫,拉兩個一樣粗的水管,一個A接到國貿,一個B接到大興機場,B的長度是A的2倍。

那麼,在正常運行的時候,密雲給同樣的水壓,在國貿和大興,單位時間接到的水,是一樣多的。這叫同樣的吞吐量。

但是,假如我們再源頭放兩個乒乓球,那麼兩個地方收到乒乓球的時間,差一倍。這就是延遲不同。

好,那麼,我們再深入問一下,latency和response time,有什麼區別?

看過《數據密集型應用系統設計》的人,應該清楚。第一章就有講。

latency是系統自身的延遲,比如進出接口的時間差。

而response time,是從調用方角度,包括了網絡時間。

性能指標還可分爲兩類:

  • 業務需求指標:如吞吐量(QPS、TPS)、響應時間(RT)、併發數、業務成功率等。

  • 資源約束指標:如 CPU、內存、I/O 等資源的消耗情況。

 

詳情可參考: 性能測試中服務器關鍵性能指標淺析

每類系統關注的重點還不一樣。 批處理/流處理 系統更關注吞吐量, 延遲可以適當放寬。一般來說大部分系統的硬件資源不會太差,但也不是無限的。高可用 Web 系統,既關注高併發情況下的系統響應時間,也關注吞吐量。

例如: "配置 2 核 4GB 的節點,每秒響應 200 個請求,95% 線是 20ms,最大響應時間 40ms。" 從中可以解讀出基本的性能信息: 響應時間(RT<40ms), 吞吐量(200TPS), 系統配置信息(2C4G)。 隱含的條件可能是 "併發請求數不超過 200 "。

我們可採用的手段和方式包括:

  • 使用 JDWP 或開發工具做本地/遠程調試

  • 系統和 JVM 的狀態監控,收集分析指標

  • 性能分析: CPU 使用情況/內存分配分析

  • 內存分析: Dump 分析/GC 日誌分析

  • 調整 JVM 啓動參數,GC 策略等等

1.3 性能調優總結

 

性能調優的第一步是制定指標,收集數據,第二步是找瓶頸,然後分析解決瓶頸問題。通過這些手段,找當前的性能極限值。壓測調優到不能再優化了的 TPS 和 QPS,就是極限值。知道了極限值,我們就可以按業務發展測算流量和系統壓力,以此做容量規劃,準備機器資源和預期的擴容計劃。最後在系統的日常運行過程中,持續觀察,逐步重做和調整以上步驟,長期改善改進系統性能。

我們經常說“脫離場景談性能都是耍流氓”,實際的性能分析調優過程中,我們需要根據具體的業務場景,綜合考慮成本和性能,使用最合適的辦法去處理。系統的性能優化到 3000TPS 如果已經可以在成本可以承受的範圍內滿足業務發展的需求,那麼再花幾個人月優化到 3100TPS 就沒有什麼意義,同樣地如果花一倍成本去優化到 5000TPS 也沒有意義。

Donald Knuth 曾說過“過早的優化是萬惡之源”,我們需要考慮在恰當的時機去優化系統。在業務發展的早期,量不大,性能沒那麼重要。我們做一個新系統,先考慮整體設計是不是 OK,功能實現是不是 OK,然後基本的功能都做得差不多的時候(當然整體的框架是不是滿足性能基準,可能需要在做項目的準備階段就通過 POC(概念證明)階段驗證。),最後再考慮性能的優化工作。因爲如果一開始就考慮優化,就可能要想太多導致過度設計了。而且主體框架和功能完成之前,可能會有比較大的改動,一旦提前做了優化,可能這些改動導致原來的優化都失效了,又要重新優化,多做了很多無用功。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章