溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么用Java制定性能調(diào)優(yōu)策略

發(fā)布時間:2021-10-28 16:48:06 來源:億速云 閱讀:137 作者:iii 欄目:編程語言

本篇內(nèi)容介紹了“怎么用Java制定性能調(diào)優(yōu)策略”的有關(guān)知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠?qū)W有所成!

測試 - 分析 - 調(diào)優(yōu)

性能測試攻略

性能測試是提前能發(fā)現(xiàn)性能瓶頸,保障系統(tǒng)性能穩(wěn)定的必要措施。

1.微基準性能測試

微基準性能測試可以精確定位到某個模塊或者某個方法的性能問題,特別適合做一個功能模塊或者一個方法在不同實現(xiàn)方式下的性能對比。例如,對比一個方法使用同步實現(xiàn)和非同步實現(xiàn)的性能。

2.宏基準性能測試

宏基準性能測試是一個綜合測試,需要考慮到測試環(huán)境、測試場景和測試目標。

首先看測試環(huán)境,我們需要模擬線上的真實環(huán)境。

然后看測試場景。我們需要確定在測試某個接口時,是否有其他業(yè)務接口同時也在平行運行,造成干擾。如果有,請重視,因為你一旦忽視了這種干擾,測試結(jié)果就會出現(xiàn)偏差。

最后看測試目標。我們的性能測試是要有目標的,這里可以通過吞吐量以及響應時間來衡量系統(tǒng)是否達標。不達標,就進行優(yōu)化;達標就繼續(xù)加大測試的并發(fā)數(shù),探底接口的 TPS(最大每秒事務處理量),這樣做,可以深入了解到接口的性能。除了測試接口的吞吐量和響應時間以外,我們還需要循環(huán)測試可能導致性能問題的接口,觀察各個服務器的 CPU 、內(nèi)存以及 I/O 使用率的變化。

以上就是兩種測試方法的詳解。其中值得注意的是,性能測試存在干擾因子,會使測試結(jié)果不準確。所以,我們在做性能測試時,還要注意一些問題。

1、熱身問題

當我們做性能測試時,我們的系統(tǒng)會運行得越來越快,后面的訪問速度要比我們第一次訪問的速度快上幾倍。這是怎么回事呢?

在 Java 編程語言和環(huán)境中,.Java 文件編譯成為 .class 文件后,機器還是無法直接運行 .class 文件中的字節(jié)碼,需要通過解釋器將字節(jié)碼轉(zhuǎn)換成本地機器碼才能運行。為了節(jié)約內(nèi)存和執(zhí)行效率,代碼最初被執(zhí)行時,解釋器會率先執(zhí)行這段代碼。

隨著代碼被執(zhí)行的次數(shù)增多,當虛擬機發(fā)現(xiàn)某個方法或代碼塊運行得特別頻繁時,就會把這些代碼認定為熱點代碼。為了提高熱點代碼的執(zhí)行效率,在運行時,虛擬機將會通過即時編譯器,把這些代碼編譯成與本地平臺相關(guān)的機器碼,并進行各層次的優(yōu)化,然后儲存在內(nèi)存中,之后每次運行代碼時,直接從內(nèi)存匯總獲取即可。

所以在剛開始運行的階段,虛擬機會花費很長的時間來全面優(yōu)化代碼,后面就能以最高性能執(zhí)行了。

這就是熱身過程,如果在進行性能測試時,熱身時間過長,就會導致第一次訪問速度過慢,你就可以考慮先優(yōu)化,再進行測試

2、性能測試結(jié)果不穩(wěn)定

我們在做性能測試時發(fā)現(xiàn),每次測試處理的數(shù)據(jù)集都是一樣的,但測試結(jié)果卻有差異。這是因為測試時,伴隨著很多不穩(wěn)定因為,比如機器其他進程的影響、網(wǎng)絡波動以及每個階段 JVM 垃圾回收的不同等等。

我們可以通過多次測試,將測試結(jié)果求平均,或者統(tǒng)計一個曲線圖,只要保證我們的平均值是在合理范圍之內(nèi),而且波動不是很大,這種情況下,性能測試就是通過的。

3、多 JVM 情況下的影響

如果我們的服務器有多個 Java 應用服務,部署在不同的 Tomcat 下,這就意味著我們的服務器會有多個 JVM。任意一個 JVM 都擁有整個系統(tǒng)的資源使用權(quán)。如果一臺機器上只部署單獨的一個 JVM ,在做性能測試時,測試結(jié)果很好,或者你調(diào)優(yōu)的效果很好,但在一臺機器多個 JVM 的情況下就不一定了。所以我們應該盡量避免線上環(huán)境中一臺機器部署多個 JVM 的情況。

合理分析結(jié)果,制定調(diào)優(yōu)策略

我們在完成性能測試之后,需要輸出一份性能測試報告,幫我們分析系統(tǒng)性能測試的情況。其中測試結(jié)果需要包含測試接口的平均、最大和最小吞吐量,響應時間,服務器的 CPU、內(nèi)存、I/O、網(wǎng)絡 IO 使用率,JVM 的 GC 頻率等。

通過觀察這些調(diào)優(yōu)標準,可以發(fā)現(xiàn)性能瓶頸,我們再通過自下而上的方式分析查找問題。首先從操作系統(tǒng)層面,查看系統(tǒng)的 CPU、內(nèi)存、I/O、網(wǎng)絡的使用率是否存在異常,再通過命令查找異常日志,最后通過分析日志,找到導致瓶頸的原因;還可以從 Java 應用的 JVM 層面,查看 JVM 的垃圾回收頻率以及內(nèi)存分配情況是否存在異常,分析日志,找到導致瓶頸的原因。

如果系統(tǒng)和 JVM 層面都沒有出現(xiàn)異常情況,我們可以查看應用服務業(yè)務層是否存在性能瓶頸,例如 Java 編程的問題、讀寫數(shù)據(jù)瓶頸等等。

分析查找問題是一個復雜而又細致的過程,某個性能問題可能是一個原因?qū)е碌模部赡苁菐讉€原因共同導致的結(jié)果。我們分析查找問題可以采用自下而上的方式,而我們解決系統(tǒng)性能問題,則可以采用自上而下的方式逐級優(yōu)化。下面我來介紹下從應用層到操作系統(tǒng)層的幾種調(diào)優(yōu)策略。

1、優(yōu)化代碼

應用層的問題代碼往往會因為耗盡系統(tǒng)資源而暴露出來。例如,我們某段代碼導致內(nèi)存溢出,往往是將 JVM 中的內(nèi)存用完了,這個時候系統(tǒng)的內(nèi)存資源消耗殆盡了,同時也會引發(fā)JVM 頻繁地發(fā)生垃圾回收,導致 CPU 100% 以上居高不下,這個時候又消耗了系統(tǒng)的CPU 資源。

還有一些是非問題代碼導致的性能問題,這種往往是比較難發(fā)現(xiàn)的,需要依靠我們的經(jīng)驗來優(yōu)化。例如,我們經(jīng)常使用的 LinkedList 集合,如果使用 for 循環(huán)遍歷該容器,將大大降低讀的效率,但這種效率的降低很難導致系統(tǒng)性能參數(shù)異常。

這時有經(jīng)驗的同學,就會改用 Iterator (迭代器)迭代循環(huán)該集合,這是因為 LinkedList是鏈表實現(xiàn)的,如果使用 for 循環(huán)獲取元素,在每次循環(huán)獲取元素時,都會去遍歷一次List,這樣會降低讀的效率。

2、優(yōu)化設計

面向?qū)ο笥泻芏嘣O計模式,可以幫助我們優(yōu)化業(yè)務層以及中間件層的代碼設計。優(yōu)化后,不僅可以精簡代碼,還能提高整體性能。例如,單例模式在頻繁調(diào)用創(chuàng)建對象的場景中,可以共享一個創(chuàng)建對象,這樣可以減少頻繁地創(chuàng)建和銷毀對象所帶來的性能消耗。

3、優(yōu)化算法

好的算法可以幫助我們大大地提升系統(tǒng)性能。例如,在不同的場景中,使用合適的查找算法可以降低時間復雜度。

4、時間換空間

有時候系統(tǒng)對查詢時的速度并沒有很高的要求,反而對存儲空間要求苛刻,這個時候我們可以考慮用時間來換取空間。

例如,我在 03 講就會詳解的用 String 對象的 intern 方法,可以將重復率比較高的數(shù)據(jù)集存儲在常量池,重復使用一個相同的對象,這樣可以大大節(jié)省內(nèi)存存儲空間。但由于常量池使用的是 HashMap 數(shù)據(jù)結(jié)構(gòu)類型,如果我們存儲數(shù)據(jù)過多,查詢的性能就會下降。所以在這種對存儲容量要求比較苛刻,而對查詢速度不作要求的場景,我們就可以考慮用時間換空

5、空間換時間

這種方法是使用存儲空間來提升訪問速度?,F(xiàn)在很多系統(tǒng)都是使用的 MySQL 數(shù)據(jù)庫,較為常見的分表分庫是典型的使用空間換時間的案例。

因為 MySQL 單表在存儲千萬數(shù)據(jù)以上時,讀寫性能會明顯下降,這個時候我們需要將表數(shù)據(jù)通過某個字段 Hash 值或者其他方式分拆,系統(tǒng)查詢數(shù)據(jù)時,會根據(jù)條件的 Hash 值判斷找到對應的表,因為表數(shù)據(jù)量減小了,查詢性能也就提升了。

6、參數(shù)調(diào)優(yōu)

以上都是業(yè)務層代碼的優(yōu)化,除此之外,JVM、Web 容器以及操作系統(tǒng)的優(yōu)化也是非常關(guān)鍵的。

根據(jù)自己的業(yè)務場景,合理地設置 JVM 的內(nèi)存空間以及垃圾回收算法可以提升系統(tǒng)性能。例如,如果我們業(yè)務中會創(chuàng)建大量的大對象,我們可以通過設置,將這些大對象直接放進老年代。這樣可以減少年輕代頻繁發(fā)生小的垃圾回收(Minor GC),減少 CPU 占用時間,提升系統(tǒng)性能。

Web 容器線程池的設置以及 Linux 操作系統(tǒng)的內(nèi)核參數(shù)設置不合理也有可能導致系統(tǒng)性能瓶頸,根據(jù)自己的業(yè)務場景優(yōu)化這兩部分,可以提升系統(tǒng)性能。

兜底策略,確保系統(tǒng)穩(wěn)定性

第一,限流,對系統(tǒng)的入口設置最大訪問限制。這里可以參考性能測試中探底接口的 TPS。同時采取熔斷措施,友好地返回沒有成功的請求。

第二,實現(xiàn)智能化橫向擴容。智能化橫向擴容可以保證當訪問量超過某一個閾值時,系統(tǒng)可以根據(jù)需求自動橫向新增服務。

第三,提前擴容。這種方法通常應用于高并發(fā)系統(tǒng),例如,瞬時搶購業(yè)務系統(tǒng)。這是因為橫向擴容無法滿足大量發(fā)生在瞬間的請求,即使成功了,搶購也結(jié)束了。

目前很多公司使用 Docker 容器來部署應用服務。這是因為 Docker 容器是使用 Kubernetes 作為容器管理系統(tǒng),而 Kubernetes 可以實現(xiàn)智能化橫向擴容和提前擴容Docker 服務。

“怎么用Java制定性能調(diào)優(yōu)策略”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI