(點選上方公眾號,可快速關註)
來源:coyee ,
coyee.com/article/11118-5-great-java-performance-optimization-tricks
要對你的 java 程式碼進行最佳化,需要理解 java 不同要素之間的相互作用,以及它是如何與其執行時的作業系統進行互動的。使用下麵這五個技巧和資源,開始學習如何分析和最佳化你的程式碼吧。
在我們開始之前, 你也許會擔心許可的問題. Java 為 Oracle 公司所有,遵循 Oracle 的 BCL 許可,該許可證不是一個免費/開源許可證。即便如此, 仍然有許多開源專案由 Oracle 公司的 Java 開發。 OpenJDK 是 java 平臺自由軟體的實現,遵循 GPL v2 許可。 (更多資訊請參見維基百科 Free Java implementations。)
https://en.wikipedia.org/wiki/Free_Java_implementations
讓我們開始吧
效能最佳化取決於多個因素,包括垃圾收集、虛擬機器和底層作業系統(OS)設定。有多個工具可供開發人員進行分析和最佳化時使用,你可以透過閱讀 Java Tools for Source Code Optimization and Analysis 來學習和使用它們。如果你正苦苦掙扎於術語和 Java 的原理,可以先去檢視 Livecoding Java category page,上面有直播,存檔的影片,以及一些其他有用的資訊。
Java Tools for Source Code Optimization and Analysis
https://dzone.com/articles/java-tools-source-code
Livecoding Java category page
https://www.livecoding.tv/categories/java/
“視情況而定”
必須要明白的是,沒有兩個應用程式可以使用相同的最佳化方式,也沒有完美的最佳化 java 應用程式的參考路徑。使用最佳實踐並且堅持採用適當的方式處理效能最佳化。想要達到真正最高的效能最佳化,你作為一個 Java 開發人員,需要對 Java 虛擬機器(JVM)和底層作業系統有正確的理解:
-
JVM 和底層作業系統:Java 虛擬機器是任何 Java 程式的家。閱讀 JVM internals guide 瞭解更多有關於 JVM 內部和作業系統差異的內容。
-
JVM 分佈模型:Java 分佈模型為您的應用程式處理多個JVM實體。分佈模型提高了應用程式的效能,因為它獲得更多的資源來工作。你可以用兩種方法繼續最佳化。第一種方法是在一個堆大小為2GB或8GB的單伺服器執行多個 JVM。第二種方法是在多個伺服器上執行單個 JVM。正確方法的選擇取決於多個因素,包括可用性和響應性。
-
JVM 體系結構:選擇正確的 JVM 體系結構對於效能來說是很重要的。你可以選擇 64 位或者 32 位的 JVM 機器。 一般來說,32 位 JVM 的效能比它對應的 64 位 JVM 要好。 只有當你需要的堆大小大於 3 GB 時,才選擇 64 位的 JVM。
https://dzone.com/articles/understanding-jvm-internals
清楚了效能最佳化和其要素,現在我們可以專註於那些可以最佳化你的Java應用的技巧.
1. 調整垃圾收集(GC)
由於垃圾收集的複雜性,很難發現你的應用的準確效能.不過,如果你真的想最佳化你的應用,你應該相應地處理垃圾收集.通用的準則是調整GC設定並同時執行效能分析.
一旦你對結果感到滿意,你可以停止該過程並尋求其他最佳化方式.確保除了在平均事務處理時間之外,你還留心了異常值.這些異常值是造成Java應用緩慢的真正的罪魁禍首並且很難找到.
此外,你要明白應用執行期間效能下降的效應.在每單個cpu時鐘內的緩慢操作是可以忽略的,但在每單個資料庫事務中的緩慢操作則是非常昂貴的消耗.但是你應該根據效能短板選擇你的最佳化策略,並應該根據工作負載來最佳化應用.
2. 正確地選擇適合你的GC演演算法
讓我們更深入地探討GC最佳化.畢竟,GC最佳化是要處理的整個最佳化問題中最基本的.目前,Java中有四種供你選擇的垃圾收集演演算法.每種演演算法滿足不同的需求,因此你要選擇(適合你的需求的).很多開發人員正是因為不瞭解GC演演算法而未能最佳化他們的應用.
這四個演演算法分別是序列回收器,並行/吞吐量回收器,CMS回收器和G1回收器.想要瞭解更多關於每種垃圾收集器的資訊及它們是如何工作的,請檢視這篇來自Takipi部落格的非常棒的文章Garbage Collectors—Serial vs. Parallel vs. CMS vs. G1. 這篇文章同時還討論了Java8對GC演演算法的影響及其他細節上的改變.讓我們再回到GC演演算法上,根據Understanding Java Garbage Collection這篇文章所述,併發標記和清除GC(即”CMS”)演演算法才是適合網路服務端應用的最佳演演算法.並行GC演演算法適合那些內部可預測的應用.
Garbage Collectors—Serial vs. Parallel vs. CMS vs. G1
http://blog.takipi.com/garbage-collectors-serial-vs-parallel-vs-cms-vs-the-g1-and-whats-new-in-java-8/
Understanding Java Garbage Collection
http://www.cubrid.org/blog/dev-platform/understanding-java-garbage-collection/
G1和CMS是併發操作的理想選擇,但仍然會引起(應用)頻繁停頓.實際的選擇取決於你如何取捨.舉例來說,儘管選擇並行演演算法會帶來更長的GC停頓時間,但相較於其他GC演演算法,選擇並行演演算法仍是一個好主意.
3.Java 堆
Java記憶體堆在迎合記憶體需求方面擔任了至關重要角色.通常更好的做法是初始時分配最小的堆,然後透過持續的測試不斷增加它的大小.大多數時候最佳化問題都可以透過增加堆的大小解決,但如果存在大量的GC開銷,則該解決方案不起作用.
GC開銷還會使吞吐量急劇下降,進而使得應用難以形容的慢.此外,及早調整GC可以幫助你避免堆大小分配的問題.開始的時候,你可以選擇任何1GB到8GB的堆大小.當你選擇正確的堆大小,老生代和新生代物件的概念也就不需要了.總而言之,堆大小應該取決於老生代和新生代物件的比率,之前的GC最佳化和物件集合(即所有物件佔用的記憶體大小).
4. 關鍵應用最佳化
關鍵程式碼最佳化是最佳化你的Java應用最好的方式.如果你的應用對GC和堆最佳化沒有反應,那麼最好是做架構改進並關註於你的應用是如何處理資訊的.使用聰明的演演算法並管理好物件就能解決大量的問題,包括記憶體碎片,堆大小問題和垃圾收集的問題.
5.使用最優的函式
Java提供了多個函式來提升演演算法效率.如果你使用StringBuilder代替簡單的String,你可以得到微乎其微的效能提升.不過,我們還有其他方式在程式碼層面進行最佳化.讓我們看看下麵這些最佳化方法.
-
使用StringBuilder代替+運運算元.
-
避免使用iterator().
-
多使用棧帶來的好處.
-
避免使用正則運算式,使用Apache Commons Lang作為代替.
-
遠離遞迴.遞迴會佔用大量資源!
檢視更多關於程式碼的最佳化Top 10 Easy Performance. Optimisations in Java.
https://blog.jooq.org/2015/02/05/top-10-easy-performance-optimisations-in-java/
結論
java的效能最佳化可是一個大課題, 藉著這片文章拋磚引玉。如果您認為文章還需要新增補充,別忘了在下麵的評論中分享您的觀點。
看完本文有收穫?請轉發分享給更多人
關註「ImportNew」,提升Java技能