Java性能優化學習1:理論基礎學習與分析
性能是什么
性能:使用有限的資源在有限的時間內完成工作。
最主要的衡量因素就是時間,所以很多衡量指標,都可以把時間作為橫軸。
加載緩慢的網站,會受到搜索排名算法的懲罰,從而導致網站排名下降。 因此加載的快慢是性能優化是否合理的一個非常直觀的判斷因素,但性能指標不僅僅包括單次請求的速度,它還包含更多因素。
性能衡量指標
1、性能指標:吞吐量QPS/TPS/HPS、響應速度
2、響應時間:平均響應時間AVG、百分位數
3、并發量
4、秒開率
5、正確性
吞吐量與響應速度
現在市面上大多數都是分布式的高并發應用,而現在最常用的衡量指標就是吞吐量和響應速度。
如何理解吞吐量和響應速度呢。
可以以路口的紅綠燈為例子來模擬,當交通繁忙的時候,如果紅綠燈放行時間很長,那么一定會有某一條路口排很長的隊,這個時候對于某一輛在排隊的車來說,從他等待排隊到經過這個紅綠燈路口的時間,就是響應時間。
那么吞吐量可以理解為和響應速度有個相對的概念,如果紅綠燈時間我們讓他變短,那么這個時候每個路口對于某些車輛來說,響應時間可能會變短,但是這個時候頻繁的切換紅綠燈,就會導致單位時間通過的車輛減少,所以可以認為吞吐量減少了。
這里給定幾個確定的開發常用詞:
QPS 代表每秒查詢的數量,
TPS 代表每秒事務的數量,
HPS 代表每秒的 HTTP 請求數量等,
這都是常用的與吞吐量相關的量化指標。
需要注意的是:在性能優化的時候,我們要搞清楚優化的目標,到底是吞吐量還是響應速度。
有些時候,雖然響應速度比較慢,但整個吞吐量卻非常高,比如一些數據庫的批量操作、一些緩沖區的合并等。雖然信息的延遲增加了,但如果我們的目標就是吞吐量,那么這顯然也可以算是比較大的性能提升。
一般認為:
響應速度是串行執行的優化,通過優化執行步驟解決問題;
吞吐量是并行執行的優化,通過合理利用計算資源達到目標。
一般對于普通的業務來說,優化主要側重于響應速度,如果響應速度提升了,吞吐量也就提升了。
而現在的環境是追求高并發、高可用、能夠抵御住雙十一特別大人流的場景、甚至可能還會夾帶有云原生的概念,而這些業務場景,兩者是都需要的。
響應時間衡量
如何計算響應時間呢?
平均響應時間
也就是常說的指標AVG,能夠體現某個業務的平均處理能力。全部加起來除以總數即可。
但是這么算也有弊端,那就是如果有長尾請求的話,長尾請求的影響會被很快平均,導致很多用戶的請求變慢,這不能體現在平均耗時指標中。(什么是長尾請求:明顯高于均值的那部分占比比較小的請求,業界關于延遲有一個P99的標準,也就是說99%的請求延遲要滿足在一定耗時內,剩下的1%會大于這個耗時,而這個1%就會認為是長尾請求。)
既然這里提到了長尾請求,那就順帶講解一下長尾導致的危害、造成的原因、解決方案。
長尾危害:假設,一個接口提供服務B,有1%的可能性響應時間大于1s,如果此刻一個上游服務A需要完成一次查詢,需要同時查詢100次的話,那么服務A響應時間超過1s的概率是63%。
0.99的概率是小于1s,100次的概率是0.99^100 = 0.37,小于1s響應的時間是37%的概率。
那么請求大于1s的概率就是63%。
即使服務處理時間超過1秒的比例僅為 0.01% ,當需要同時查詢的實例數(Numbers of Servers)達到2000時,服務延時大于1秒的請求數將超過18%。
造成長尾的原因:
共享資源競爭, 周期性的垃圾回收, 運維活動(比如日志備份), 硬件或者軟件故障,網絡的抖動,都有可能造成。
解決長尾的方法:
微博motan有一種雙發機制,它可以有效解決長尾問題,同時能提升系統吞吐量。
傳統解決接口超時問題可能通過重試,在一次請求發送之后等待指定的超時時間,如果沒有返回則再請求一次,最差情況下要消耗 2 倍的超時時間。
而雙發機制則不然,在發送一次請求后等待 P90(在 T1 時間內有 90% 的請求都能返回則稱 P90=T1,通常系統的 P90 和程序設置的超時時間相比小很多)時間。
如果請求沒有返回則在此刻再次發送一次請求,在超時時間內,這兩個請求中取最快返回的那個。
當然,這里有個防雪崩機制,假如,超過一定數量的請求(比如 15%)都在進行雙發,則認為服務整體有問題,會自動停止雙發。實踐證明,雙發機制的去長尾效果非常明顯
話說回來,為了解決平均響應時間的缺點,同時還要衡量響應時間,我們引入了百分位數概念。
百分位數
這個也比較好理解。圈定一個時間范圍,把每次請求的耗時加入一個列表中,然后按照從小到大的順序將這些時間進行排序。這樣,我們取出特定百分位的耗時,這個數字就是 TP 值。可以看到,TP 值(Top Percentile)和中位數、平均數等是類似的,都是一個統計學里的術語。
它的意義是,超過 N% 的請求都在 X 時間內返回。比如 TP90 = 50ms,意思是超過 90th 的請求,都在 50ms 內返回。
這個指標也是非常重要的,它能夠反映出應用接口的整體響應情況。比如,某段時間若發生了長時間的 GC,那它的某個時間段之上的指標就會產生嚴重的抖動,但一些低百分位的數值卻很少有變化。
我們一般分為 TP50、TP90、TP95、TP99、TP99.9 等多個段,對高百分位的值要求越高,對系統響應能力的穩定性要求越高。
在這些高穩定性系統中,目標就是要干掉嚴重影響系統的長尾請求。這部分接口性能數據的收集,會采用更加詳細的日志記錄方式,而不僅僅靠指標。比如,將某個接口,耗時超過 1s 的入參及執行步驟,詳細地輸出在日志系統中。
并發量
并發量是指系統同時能處理的請求數量,這個指標反映了系統的負載能力。
在高并發應用中,僅僅高吞吐是不夠的,它還必須同時能為多個用戶提供服務。并發高時,會導致很嚴重的共享資源爭用問題,我們需要減少資源沖突,以及長時間占用資源的行為。
針對響應時間進行設計,一般來說是萬能的。因為響應時間減少,同一時間能夠處理的請求必然會增加。值得注意的是,即使是一個秒殺系統,經過層層過濾處理,最終到達某個節點的并發數,大概也就五六十左右。我們在平常的設計中,除非并發量特別低,否則都不需要太過度關注這個指標。
秒開率
現在的用戶,如果上網,試想一下,打開一個頁面如果要5-6秒那這個網頁或者說APP估計評分肯定非常低,秒開是一種特別需要重視的用戶體驗。
正確性
在進行測試的時候,發現接口響應非常流暢,把并發數增加到 20 以后,應用接口響應依舊非常迅速。
但等應用真正上線時,卻發生了重大事故,這是因為接口返回的都是無法使用的數據。
其問題原因也比較好定位,就是項目中使用了熔斷。在壓測的時候,接口直接超出服務能力,觸發熔斷了,但是壓測并沒有對接口響應的正確性做判斷,造成了非常低級的錯誤。
優化的理論方法
理論方法有很多,如木桶理論、基礎測試、Amdahal定律等等。
1、木桶理論
一只木桶若想要裝最多的水,則需要每塊木板都一樣長而且沒有破損才行。如果有一塊木板不滿足條件,那么這只桶就無法裝最多的水。
能夠裝多少水,取決于最短的那塊木板,而不是最長的那一塊。
木桶效應在解釋系統性能上,也非常適合。組成系統的組件,在速度上是良莠不齊的。系統的整體性能,就取決于系統中最慢的組件。
比如,在數據庫應用中,制約性能最嚴重的是硬盤的 I/O 問題,也就是說,硬盤是這個場景下的短板,我們首要的任務就是補齊這個短板。
2、基準測試、預熱
基準測試(Benchmark)并不是簡單的性能測試,是用來測試某個程序的最佳性能。
應用接口往往在剛啟動后都有短暫的超時。在測試之前,需要對應用進行預熱,消除 JIT 編譯器等因素的影響。而在 Java 里就有一個組件,即 JMH,就可以消除這些差異。
優化注意事項
1、把性能分析放在第一位而不是性能優化
在優化的時候不能憑借對代碼的熟悉來猜測系統的問題所在,一般來說,復雜的業務系統往往有多個影響因素,我們應該將性能分析放在第一位,而不是把性能優化放在第一位。
進行性能優化時,我們一般會把分析后的結果排一個優先級(根據難度和影響程度),從大處著手,首先擊破影響最大的點,然后將其他影響因素逐一擊破。
有些優化會引入新的性能問題,有時候這些新問題會引起更嚴重的性能下降,你需要評估這個連鎖反應,確保這種優化確實需要,同時需要使用數字去衡量這個過程,而不是靠感覺猜想。
2、進行大量試驗,不依靠小數據量
個體請求的小批量數據,可參考價值并不是非常大。響應時間可能因用戶的數據而異,也可能取決于設備和網絡條件。
合理的做法,是從統計數據中找到一些規律,比如上面所提到的平均響應時間、TP 值等,甚至是響應時間分布的直方圖,這些都能夠幫我們評估性能質量。
3、不要過早優化和過度的優化
雖然性能優化有這么多好處,但并不代表我們要把每個地方都做到極致,性能優化也是要有限度的。程序要運行地正確,要比程序運行得更快還要困難。
計算機科學的鼻祖"Donald Knuth" 曾說:“過早的優化是萬惡之源”,就是這個道理。
正確的做法是,項目開發和性能優化,應該作為兩個獨立的步驟進行,要做性能優化,要等到整個項目的架構和功能大體進入穩定狀態時再進行。
4、保持良好的編程習慣
Java
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。