十大最常见的Java性能问题
Java性能是所有Java應(yīng)用程序開發(fā)人員都關(guān)心的問題,因為快速使應(yīng)用程序與使其正常運行同等重要。 史蒂文·海恩斯(Steven Haines)使用他在Java性能問題上的個人經(jīng)驗得出的結(jié)論是, 大多數(shù)問題都有共同的根本原因 。 因此,作為績效分析師,Haines將基本績效問題分為三個基本類別:
數(shù)據(jù)庫問題 ,主要與持久性配置,緩存或數(shù)據(jù)庫連接線程池配置有關(guān)。
內(nèi)存問題 ,通常是垃圾回收配置錯誤或內(nèi)存泄漏。
并發(fā)問題 ,基本上是死鎖,網(wǎng)格鎖和線程池配置問題。
讓我們深入研究每個類別...
數(shù)據(jù)庫
由于數(shù)據(jù)庫是應(yīng)用程序功能的基本組成部分,因此它也是性能問題的基本根源。 由于對數(shù)據(jù)庫的訪問使用錯誤,連接池大小錯誤或缺少調(diào)整,可能會出現(xiàn)問題。
持久性配置
即使今天Hibernate和其他JPA實現(xiàn)提供了對數(shù)據(jù)庫訪問的微調(diào),但仍有一些其他選擇(例如急切或延遲獲取)可能會導(dǎo)致較長的響應(yīng)時間和數(shù)據(jù)庫開銷。 渴望獲取使數(shù)據(jù)庫調(diào)用減少了,但變得更加復(fù)雜,而懶惰獲取使數(shù)據(jù)庫調(diào)用變得更加簡單和快速。
當(dāng)應(yīng)用程序的負(fù)載增加并且會導(dǎo)致更大的數(shù)據(jù)庫負(fù)載時,就會出現(xiàn)問題。 因此,為了解決此問題,您可以查看業(yè)務(wù)事務(wù)計數(shù)器,數(shù)據(jù)庫計數(shù)器,但基本上是業(yè)務(wù)事務(wù)與數(shù)據(jù)庫調(diào)用之間的相關(guān)性。 為避免此類問題,您必須充分了解所使用的持久性技術(shù),正確設(shè)置所有配置選項,以便將其功能與您的業(yè)務(wù)領(lǐng)域需求配對。
快取
緩存優(yōu)化了應(yīng)用程序的性能,因為內(nèi)存中的數(shù)據(jù)比持久性的??數(shù)據(jù)訪問速度更快。 當(dāng)不使用緩存時會引起問題,因此每次需要資源時都會從數(shù)據(jù)庫中檢索它。 使用緩存時,由于配置錯誤,會出現(xiàn)問題。 這里要注意的基本事項是緩存的固定大小和分布式緩存配置。 緩存的對象是有狀態(tài)的,與提供無狀態(tài)對象的池不同。 因此,必須正確配置緩存,以免耗盡內(nèi)存。 但是,如果再次請求移除的對象怎么辦? 必須在高速緩存設(shè)置以及內(nèi)存中配置此“未命中”比率。
分布式緩存也可能會引起問題。 將緩存設(shè)置為多個服務(wù)器時,必須進行同步。 因此,緩存更新將傳播到所有服務(wù)器中的緩存。 這是實現(xiàn)一致性的方式,但這是一個非常昂貴的過程。 正確使用緩存后,應(yīng)用程序負(fù)載增加不會增加數(shù)據(jù)庫負(fù)載,但是當(dāng)緩存設(shè)置錯誤時,數(shù)據(jù)庫負(fù)載會增加,從而導(dǎo)致CPU開銷達(dá)到均勻的磁盤I / O速率。
為了解決此問題,您應(yīng)該首先檢查數(shù)據(jù)庫性能,以確定是否需要緩存。 然后,您應(yīng)該使用命中率和未命中率指標(biāo)來確定緩存大小。 但是,通過在構(gòu)建應(yīng)用程序之前正確規(guī)劃應(yīng)用程序,可以避免遇到緩存問題。 確保使用序列化和提供可伸縮應(yīng)用程序的技術(shù)。
泳池連接
池連接通常在啟動應(yīng)用程序之前創(chuàng)建,因為它們的創(chuàng)建成本很高。 連接池在事務(wù)之間共享,并且池大小限制了數(shù)據(jù)庫負(fù)載。
池大小很重要。 沒有足夠的連接使業(yè)務(wù)交易等待,數(shù)據(jù)庫使用不足。 另一方面,太多的連接會導(dǎo)致更長的響應(yīng)時間和數(shù)據(jù)庫過載。 為了解決此問題,您必須檢查您的應(yīng)用程序是在等待新的連接還是要執(zhí)行數(shù)據(jù)庫查詢。 但是,您始終可以通過優(yōu)化數(shù)據(jù)庫來避免這種情況,使用不同的池大小測試應(yīng)用程序以檢查哪種情況適合。
記憶
內(nèi)存問題與垃圾收集器和內(nèi)存泄漏有關(guān)。
垃圾收集器
垃圾回收可能會導(dǎo)致所有線程停止以回收內(nèi)存。 當(dāng)此過程花費太多時間或發(fā)生得太頻繁時,就會出現(xiàn)問題。 它的基本癥狀是CPU峰值和較大的響應(yīng)時間。 要解決此問題,您可以配置-verbosegc參數(shù),使用性能監(jiān)視工具來查找發(fā)生主要GC的過程,并使用一種工具來監(jiān)視堆使用情況和可能的CPU峰值。 盡管可以通過配置堆大小和循環(huán)JVM來限制它,但是幾乎不可能避免該問題。
內(nèi)存泄漏
Java中的內(nèi)存泄漏可能以不同于C或C ++的方式發(fā)生,因為它們更多地是參考管理問題。 在Java中,即使不再使用對象,也可以保留對對象的引用。 這可能會導(dǎo)致OutOfMemory錯誤,并要求重新啟動JVM。 當(dāng)內(nèi)存使用量增加并且堆內(nèi)存不足時,就會發(fā)生內(nèi)存泄漏問題。 要解決此問題,可以正確配置JVM參數(shù)。 為避免必須處理內(nèi)存泄漏,在對內(nèi)存泄漏進行編碼時應(yīng)注意-敏感的Java集合或會話管理。 您可以與同事共享內(nèi)存泄漏避免技巧,讓專家查看您的應(yīng)用程序代碼,并使用工具來避免內(nèi)存泄漏和分析堆。
并發(fā)
并發(fā)發(fā)生在同時執(zhí)行多個計算時。 Java使用同步和鎖來管理多線程。 但是同步可能會導(dǎo)致線程死鎖,網(wǎng)格鎖和線程池大小問題。
線程死鎖
當(dāng)兩個或多個線程試圖訪問相同的資源,而一個線程正在等待另一個線程釋放資源時,則發(fā)生線程死鎖,反之亦然。 發(fā)生死鎖時,JVM將耗盡所有線程,并且應(yīng)用程序會變慢。 死鎖很難重現(xiàn)。 因此,解決死鎖問題的一種方法是在兩個線程死鎖時捕獲線程轉(zhuǎn)儲,并檢查線程的堆棧跟蹤。 為避免此問題,您最好使您的應(yīng)用程序及其資源盡可能不變,使用同步并檢查潛在的線程交互。
線程僵局
當(dāng)使用過多的同步并因此花費太多時間等待單個資源時,可能會發(fā)生線程僵局。 要注意這一點,您必須同時具有較慢的響應(yīng)時間和較低的CPU使用率,因為許多線程嘗試訪問同一代碼部分,并且它們正在等待具有該代碼部分的代碼部分完成。 那么,您該如何解決呢? 您必須首先檢查線程在哪里等待以及原因。 然后,您應(yīng)該根據(jù)業(yè)務(wù)需求消除同步要求。
線程池配置鎖
當(dāng)應(yīng)用程序使用應(yīng)用程序服務(wù)器或Web容器時,線程池用于控制并發(fā)處理的請求。 如果此線程池很小,則請求將等待很多,但是如果線程池太大,則處理資源將變得很忙。 因此,在較小的池中,CPU利用率不足,但線程池利用率為100%,而在較大的池中,CPU則非常繁忙。
您可以通過檢查線程池利用率和CPU利用率并確定是增大還是減小池大小來輕松解決此問題 。 為了避免這種情況,您必須調(diào)整線程池,但這并非那么容易。
最后,可能發(fā)生的兩個基本問題是事后考慮的性能問題,或最終用戶會注意到的性能問題。
第一種情況是一個常見問題。 通常,開發(fā)人員會創(chuàng)建一個可以正常運行但在性能測試中失敗的應(yīng)用程序。 為了解決這個問題,他們通常必須對應(yīng)用程序進行體系結(jié)構(gòu)審查,而性能分析工具似乎非常方便。 為避免此問題,請在開發(fā)應(yīng)用程序時嘗試測試性能,因此持續(xù)集成是關(guān)鍵。
對于第二種情況,當(dāng)應(yīng)用程序的最終用戶通知您存在性能問題時會發(fā)生什么? 有避免這種情況的工具,例如JMX來檢查服務(wù)器的行為。 商業(yè)交易績效結(jié)果與JMX結(jié)果結(jié)合在一起也可能會有所幫助。 方法級響應(yīng)時間檢查業(yè)務(wù)事務(wù)中調(diào)用的所有方法,并找到應(yīng)用程序的熱點。 因此,最好使用這些工具之一,以使最終用戶永遠(yuǎn)不會警告您性能。
有興趣了解更多嗎? 然后,您應(yīng)該在此處下載相關(guān)的電子書。
翻譯自: https://www.javacodegeeks.com/2015/02/top-10-common-java-performance-problems.html
總結(jié)
以上是生活随笔為你收集整理的十大最常见的Java性能问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: eui设置教程(eui安装教程)
- 下一篇: 正确获取Java事件通知