JVM性能調優(yōu)的評估指標及調優(yōu)示例

上一篇 <<<FullGC、MinorGC、STW等常見問題如何解答
下一篇 >>>Class文件分析一個類為啥最多支持65535個接口


整體評估指標說明

1.吞吐量: 運行用戶代碼占總時間的比例
總運行時間:用戶線程程序的運行時間(100s)+GC內存回收的時間 (1s)
比如程序運行時間100s/內存回收時間 垃圾回收1s 則吞吐量為100/101=99%
2.GC負荷:與吞吐量相反,指應用花在GC上的時間百分比
上例GC負荷為:1/101=1%
3.暫停時間:應用線程花在GC stop-the-world 的時間
暫時時間越小越好
4.GC頻率:次數(shù)/GC頻率越多,stw暫停時間越短;GC回收頻率次數(shù)越少、stw暫停時間越長
5.反應速度:從一個對象變成垃圾道這個對象被回收的時間
吞吐量優(yōu)先的收集器:Parallel并行收集器【Jdk8默認收集器】
響應時間優(yōu)先的收集器:CMS(老年代)/ParNew(新生代)-注重stw時間越少
G1/ZGC同時注重吞吐量和響應時間優(yōu)先

JVM調優(yōu)方案

優(yōu)化核心思路:
1、通過堆內存設置減少老年代垃圾回收的次數(shù)
2、配置垃圾回收器,減少STW的時間

1.避免用戶線程暫停時間STW比較短

a.堆內存空間一定要充足,垃圾回收和最大堆內存無關,只和初始內存有關。
b.項目啟動堆內存初始值與最大值一定保持一致,可減少垃圾回收的次數(shù),提高吞吐量;
c.不建議調用System.gc(),容易造成STW;
d.不要在堆內存中存放大對象和全局變量,容易觸發(fā)fullgc
e.合理根據項目堆內存情況,選擇收集器

2.合理設定堆的初始大小和選擇合理的垃圾收集器

a.起步階段的個人網站,建議堆內存1GB 可以串行SerialGC,建議使用并行Parallel GC
b.有一定訪問量的網站或APP,建議堆內存2g 建議使用Parallel GC
c.并發(fā)適中的APP或普通數(shù)據處理,建議堆內存4g 老年代CMS/新生代parnew
d.適用于并發(fā)要求較高的APP,建議堆內存8G(要16G的可以集群)建議G1收集器 注重低延遲和吞吐量

必填參數(shù)

-Xmx 堆最大可用值 測試結果:默認4G----物理內存的1/4
-Xms 堆初始值 測試結果:最大內存的1/16-----物理內存的1/64
-XX:+HeapDumpOnOutOfMemoryError 內存溢出的時候打印內存快照
-XX:HeapDumpPath=hdpserver_oom.hprof 內存溢出的時候內存快照保存路徑

tips:
a、-Xmx和-Xms在內存不大的時候建議相同,內存很大的時候,建議配成2:1
b、內存溢出的快照配置很可能幾個月不出現(xiàn),但建議配置上,方便問題出現(xiàn)時的排查
c、垃圾回收器在JDK8之前建議用CMS,JDK8及之后建議用G1。

優(yōu)化參數(shù)

-XX:+PrintGC 每次觸發(fā)GC的時候打印相關日志
-XX:+PrintGCDetails 更詳細的GC日志
堆設置
-Xmn 新生代堆最大可用值 默認是堆的1/3,官方推薦配置為整個堆的3/8
-XX:NewRatio 配置新生代與老年代占比 默認1:2 建議值:1:2或1:3 -XX:NewRatio=3
-XX:SurvivorRatio 用來設置新生代中eden空間和from/to空間的比例=eden/from=den/to 默認8:1
-XX:PermSize 初始化永久內存區(qū)域大小,默認4M,超出的話可能出現(xiàn)PermGen space錯誤。
-XX:MaxPermSize 設置永久內存區(qū)域最大大小
-XX:NewSize 作用跟-XX:NewRatio相似,不同的是精確的數(shù)值
-XX:MaxNewSize 設置最大Java新對象生產堆內存,
NewSize和MaxNewSize最好設成一致,數(shù)值都是1024的整數(shù)倍并且大于1MB。
-XX:MaxTenuringThreshold 設置垃圾最大年齡
-XX:GCTimeRatio 設置垃圾回收時間占程序運行時間的百分比,垃圾回收時間占程序運行時間百分比的公式為1/(1+n) ,如果n=19表示java可以用5%的時間來做垃圾回收,1/(1+19)=1/20=5%。
-Xss 我們線程??臻g大小 –Xss1m,jdk5.0前是256k---配置不適合太高
1.8元空間設置大小
-XX:MetaspaceSize 初始空間大小,達到該值就會觸發(fā)垃圾收集進行類型卸載,同時GC會對該值進行調整:如果釋放了大量的空間,就適當降低該值;如果釋放了很少的空間,那么在不超過MaxMetaspaceSize時,適當提高該值。
-XX:MaxMetaspaceSize 最大空間,默認是沒有限制的。

代碼演示

1.默認值測試

/**
 *
 *  命令查看默認值:
 *  最大內存4G
 *  初始內存:最大內存的1/16
 *  垃圾回收器:Parallel Scavenge收集器
 *
 *  java -XX:+PrintCommandLineFlags -version
 * -XX:InitialHeapSize=268435456 -XX:MaxHeapSize=4294967296 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC
 *
 * 代碼查看默認值:
 * 最大內存:4G
 * 新生代:老年代= 87360:174784 = 1:2
 * eden:from:to = 8:1:1
 *
 * 最大內存3959.5M
 * 可用內存244.76746368408203M
 * 已經使用內存247.5M
 * Heap 堆信息
 *  def new generation   total 78656K, used 4197K [0x00000006c0000000, 0x00000006c5550000, 0x0000000715550000)
 *   eden space 69952K,   6% used [0x00000006c0000000, 0x00000006c0419618, 0x00000006c4450000)
 *   from space 8704K,   0% used [0x00000006c4450000, 0x00000006c4450000, 0x00000006c4cd0000)
 *   to   space 8704K,   0% used [0x00000006c4cd0000, 0x00000006c4cd0000, 0x00000006c5550000)
 *  tenured generation   total 174784K, used 0K [0x0000000715550000, 0x0000000720000000, 0x00000007c0000000)
 *    the space 174784K,   0% used [0x0000000715550000, 0x0000000715550000, 0x0000000715550200, 0x0000000720000000)
 *  Metaspace       used 2719K, capacity 4486K, committed 4864K, reserved 1056768K
 *   class space    used 292K, capacity 386K, committed 512K, reserved 1048576K
 *
 */
public class 默認值測試 {
    public static void main(String[] args) {
        System.out.print("最大內存");
        System.out.println(Runtime.getRuntime().maxMemory() / 1024.0 / 1024 + "M");
        System.out.print("可用內存");
        System.out.println(Runtime.getRuntime().freeMemory() / 1024.0 / 1024 + "M");
        System.out.print("已經使用內存");
        System.out.println(Runtime.getRuntime().totalMemory() / 1024.0 / 1024 + "M");
    }
}

2.吞吐量測試

/**
 * -XX:PermSize=32M -Xmx32M -Xms1M -XX:+UseSerialGC -XX:+PrintGCDetails
 * 非堆內存32M,堆內存最大32M,最小1M,使用串行垃圾回收器
 * 啟動GC-96次 執(zhí)行GC-20次 吞吐量100
 *
 * -XX:PermSize=32M -Xmx32M -Xms32M -XX:+UseSerialGC -XX:+PrintGCDetails
 * 非堆內存32M,堆內存最大32M,最小32M,使用串行垃圾回收器
 * 啟動GC-39次 執(zhí)行GC-20次 吞吐量130
 *
 * -XX:PermSize=32M -Xmx512M -Xms32M -XX:+UseSerialGC -XX:+PrintGCDetails
 * 非堆內存32M,堆內存最大512M,最小32M,使用串行垃圾回收器
 * 啟動GC-39次 執(zhí)行GC-19次 吞吐量130
 *
 * -XX:PermSize=32M -Xmx512M -Xms512M -XX:+UseSerialGC -XX:+PrintGCDetails
 * 非堆內存32M,堆內存最大512M,最小512M,使用串行垃圾回收器
 * 啟動GC-1次 執(zhí)行GC-1次 吞吐量140
 *
 * ===================結論:===================================
 * =======================1、垃圾回收次數(shù)和最大堆內存大小無關,只和初始內存有關系。============
 * =======================2、最大堆內存和初始堆內存設置的一樣,可以減少垃圾回收次數(shù)============
 * =======================3、初始堆內存會影響到吞吐量,兩個值都越大吞吐量就越高============
 * =======================4、垃圾回收次數(shù)越少,吞吐量越高============
 */
@SpringBootApplication
@RestController
public class 吞吐量測試 {
    public static void main(String[] args) {
        SpringApplication.run(吞吐量測試.class);
    }

    @RequestMapping("/test2")
    public void test(){
    }
}

3.垃圾回收器測試

/**
 * -XX:PermSize=32M -Xmx64M -Xms64M -XX:+UseSerialGC -XX:+PrintGCDetails
 * 啟動GC-19次 執(zhí)行GC-10次 吞吐量95
 *
 * -XX:PermSize=32M -Xmx64M -Xms64M -XX:+UseParNewGC -XX:+PrintGCDetails
 * 啟動GC-19次 執(zhí)行GC-10次 吞吐量100
 *
 * -XX:PermSize=32M -Xmx64M -Xms64M -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails
 * 啟動GC-20次 執(zhí)行GC-10次 吞吐量103
 *
 * -XX:PermSize=32M -Xmx64M -Xms64M -XX:+UseG1GC -XX:+PrintGCDetails
 * 啟動GC-17次 執(zhí)行GC-8次 吞吐量102
 *
 * ===================結論:===================================
 * =======================1、最好使用并行收集器,因為并行收集器速度比串行吞吐量高,速度快。============
 */
@SpringBootApplication
@RestController
public class 垃圾回收器測試 {
    public static void main(String[] args) {
        SpringApplication.run(垃圾回收器測試.class);
    }

    @RequestMapping("/test")
    public void test(){
    }
}

相關文章鏈接:
<<<JVM整體內存結構的圖解,直觀明了
<<<javap命令查看對象信息及操作方法在JVM層的實現(xiàn)原理
<<<javap命令反查匯編指令匯總
<<<ClassLoader類加載器順序Demo測試與雙親委派源碼解讀
<<<自定義SPI和熱部署技術破壞類加載器的雙親委派模式
<<<JVM中對象如何完成空間分配和初始化工作
<<<JVM元空間(方法區(qū))和棧內存溢出原因及解決方案
<<<JVM堆內存溢出和內存泄露問題定位和解決
<<<JVM常見死鎖問題產生原因和多種診斷方式
<<<服務器CPU飆升為100%問題排查及如何避免
<<<JVM內存診斷命令和排查工具匯總
<<<JVM新生代老年代算法匯總圖解
<<<JVM垃圾回收不要手動System.gc的真正原因
<<<JVM垃圾回收引用計數(shù)法和根搜索算法圖解
<<<JVM垃圾回收STW(Stop-The-World)代碼演示
<<<JVM垃圾回收器的發(fā)展歷程及使用場景匯總
<<<JVM串行并行垃圾回收器的關注點
<<<一張圖看懂CMS垃圾回收器的底層原理
<<<G1能作為JDK9默認垃圾回收器的優(yōu)勢分析
<<<CMS和G1的漏標問題解決及三色標記算法圖解
<<<GC中新生代進入老年代的方式匯總
<<<GC常用日志參數(shù)配置及分析工具說明
<<<FullGC、MinorGC、STW等常見問題如何解答

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容