1 導論
JVM主要有兩類調優標志:布爾標志和附帶參數標志
布爾標志:-XX:+FlagName表示開啟,-XX:-FlagName表示關閉。
附帶參數標志:-XX:FlagName=something,表示將標志FlagName的值設置為something。
2 性能測試方法
性能測試4項原則:
2.1 原則1:測試真實應用
2.2 原則2:理解處理時間、吞吐量和響應時間
2.3 原則3:用統計方法應對性能的變化
2.4 原則4:盡早頻繁測試
3 性能調優工具
3.1 Java監控工具
jcmd,jconsole,jhat,jmap,jinfo,jstack,jstat,jvisualvm
3.2 性能分析工具
采用分析器,探查分析器,本地分析器
3.3 性能關注指標
CPU使用率,內存使用率,磁盤使用率,網絡使用率
4 JIT編譯器
即時(Just-In-Time, JIT)編譯器是Java虛擬機的核心。對JVM性能影響最大的莫過於編譯器的,而選擇編譯器是運行Java程序首先有做的。
4.1 選擇編譯器類型
Client(-client)、Server(-server)或二者同用
4.2 JIT編譯器版本
JIT編譯器版本有3中:
32位client編譯器
32位server編譯器
64位server編譯器
如果是32位操作系統,則必須使用32位的JVM。如果是64位操作系統,則既可以選擇32位的JVM,也可以選擇64位JVM。
4.3 編譯細節
不用擔心小方法,如getter和setter,因為他們很容易內聯。
需要編譯的代碼在編譯隊列中。
代碼緩存是有限的資源。
代碼越簡單,優化越多。
5 垃圾收集
5.1 概述
垃圾收集由兩步構成:查找不再使用的對象,以及釋放這些對象所管理的內存。
分代垃圾收集器,老年代,新生代。
GC算法,Serial垃圾收集器,Throughput垃圾收集器,CMS收集器,G1垃圾收集器。
5.2 GC調優基礎
調整堆的大小,初始堆Xms,最大堆Xmx。
代空間的調整,新生代和老年代的空間占用比率,初始大小。
控制並發。
自適應調整
6 堆內存最佳實踐
6.1 堆分析
淺對象大小、保留對象大小及深對象大小。
一個對象的淺大小,指的是該對象本身的大小。如果櫃對象包含一個指向另一個對象的引用,4字節或8字節的引用會計算在內,但是目標對象的大小不會包含進來。深大小則包含那些對象的大小。深大小和保留大小的區別在於那些存在共享的對象。
內存溢出錯誤(OutofMemoryError, OOM)一般在以下集中情形會拋出:
JVM沒有原生內存可用。
元空間(或永久代)內存不足。
JVM堆本身內存不足。
JVM執行GC耗時太多。
6.2 減少內存使用
減少對象大小、對象的延遲初始化、使用規范化對象、對象池化、弱引用、軟引用
7 線程與同步的性能
7.1 線程池與ThreadPoolExecutor
調節線程池的大小對獲得最好的性能至關重要,包括最小線程數和最大線程數。
線程池工作方式:有一個或多個隊列,任務被提交到這個(些)隊列中,一定數量的線程會從這個(些)隊列中取任務,然后執行。
7.2 線程同步
同步對性能有兩個方面的影響:
1) 應用在同步塊上所花的時間會影響到該應用的可伸縮性;
2) 獲取同步鎖需要一些CPU周期,所以也會影響性能。
如何避免同步:
1) 在每個線程中使用不同的對象;
2) 基於CAS的替代方案(volatile,原子類型)。
7.3 線程調優
1) 調節線程棧大小-Xss;
2) 自旋鎖;
3) 調整線程優先級;
8 數據庫性能最佳實踐
8.1 預處理語句與語句池
大多數情況下,進行JDBC調用時,推薦使用PreparedStatement,盡量避免直接使用Statement。預處理語句讓數據庫有機會重用已經執行過的SQL信息,節省之后運行的預處理語句的開銷,提升執行效率。但是,首次使用預處理語句時,數據庫會耗費更多的執行時間,因為它需要設置和保存相應的信息。如果這個語句僅使用一次,這些額外的工作就被浪費了,這種情況下,使用常規的語句(Statement)可能是更好的選擇。
8.2 JDBC連接池
創建數據庫連接是非常耗時的操作,所有的JDBC連接都應源自連接池。
8.3 結果集的處理
通過PreparedStatement對象的setFetchSize()方法可以控制JDBC驅動程序一次返回多少行數據。