【JVM實戰】JVM參數調優

JVM參數調優

一、調優基本概念

在調整性能時,JM有三個組件

  1. 堆大小調整
  2. 垃圾收集器調整
  3. JIT編譯器調整

大多數調優選項都與調整堆大小和選擇的垃圾收集器有關

同樣,JIT編譯器對性能也有很大影響,但是這個對程序員自身要求非常高。

通常,在調優Java應用程序時,重點是以下兩個主要目標之一:

  • 響應性:應用程序或系統對請求的數據進行響應的速度,對於專注於響應性的應用程序,長的暫停時間是不可接受的,重點是在短時間內做出迴應。
  • 吞吐量:側重於在特定時間段內最大化應用程序的工作量,對於專注於吞吐量的應用程序,高暫停時間是可接受的。

一般而言,系統瓶頸核心還是在應用代碼,一般情況下無需過多調優,而且JVM本身在不斷優化的過程。

二、常用JVM參數

文章圍繞Java8,下面的一些參數,在JDK9之後就被淘汰了,加紅進行了凸顯。

參數 說明
-XX:+AlwaysPreTouch JVM啓動時分配內存,非使用時再分配
-XX:ErrorFile= filename 崩潰日誌
-XX:+TraceClassLoading 跟蹤類加載信息
-XX:+PrintClassHistogram 按下Ctr+ Break後,打印類的信息
-Xmx -Xms 最大堆和最小堆
-xx:permSize, -xx:metaspaceSize 永久代/元數據空間
-XX:+HeapDumpOnOutOfMemoryError 0OM時導出堆到文件
-XX:+HeapDumpPath OOM時堆導出的路徑
-XX:+OnOutOfMemoryError JVM啓動時分配內存,非使用時再分配在OOM時,執行一個腳本
java-XX:+PrintFlagsFinal -version  打印所有的-XX參數和默認值

通用GC參數

參數 說明
-XX:ParallelGCThread 並行GC線程數量
-XX:ConcGCThreads 併發GC線程數量
-XX:MaxGCPauseMillis 最大停頓時間,單位毫秒。GC盡力保證回收時間不超過設定值
-XX:GCTimeRatio 0-100的取值範圍,表示垃圾收集時間佔總時間的比,默認99,即最大允許1%時間進行GC
-XX. SurvivorRatio 設置Eden區大小和 Survivor區大小的比例, 8表示兩個 Survivor:Eden=2:8,即一個 Survivor佔年輕代的1/10
-XX:NewRatio 新生代和老年代的比,4表示新生代老年代=1:4,即年輕代佔堆的1/5
-verbose:gc, -XX;+printGC 打印GC的簡要信息
-XX:+PrintGCDetails 打印GC詳細信息
-XX:+PrintGCTimeStamps 打印CG發生的時間戳
-Xloggc:log/gc.log 指定 GC log的位置,以文件輸出
-XX:ParallelGCThread 每次一次GC後,都打印堆信息

三、GC調優思路

首先準備環境

創建一個springboot的空項目,在啓動類部分添加一下代碼,打包,放在阿里雲服務器上運行。

測試環境:JVM配置爲1核2G,JAVA8,固定設置堆大小 1G

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
        // 每333毫秒創建150線程,每個線程創建一個512kb的對象,最多一秒同時存在450線程,佔用內存225m,查看6C的情況
        Executors.newScheduledThreadPool(1).scheduleAtFixedRate(() -> {
            new Thread(() -> {
                for (int i = 0; i < 150; i++) {
                    try {
                        //  不幹活,專門創建512kb的小對象
                        byte[] temp = new byte[1024 * 512];
                        Thread.sleep(new Random().nextInt(100)); // 隨機睡眠200毫秒秒以內
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }, 1000, 333, TimeUnit.MILLISECONDS);
    }
}

在運行之前要記得指定一下堆的大小

java -Xmx1024m -jar xxx.jar

啓動是正常的
在這裏插入圖片描述
上面已經能看到端口號了,但是我們這裏用jcmd象徵的看一下
在這裏插入圖片描述
我們看一下堆的使用情況
在這裏插入圖片描述
裏面的數據都是動態的。

我們看一下調優的思路

  1. 分析場景。例如:啓動速度慢;偶爾出現響應慢於平均水平或者出現卡頓
  2. 確定目標。內存佔用、低延時、吞吐量
  3. 收集日誌。通過參數配置收集GC日誌;通過JDK工具查看GC狀態(例如jstat 實時查看)
  4. 分析日誌。使用工具輔助分析日誌,查看GC次數,GC時間(事後分析)
  5. 調整參數。切換垃圾收集器或者調整垃圾收集器參數

前兩點的話,要和具體場景結合起來。文章主要展示整個過程該怎麼走(相當於工具說明書),具體問題要具體分析。

java -Xmx1024m -Xloggc:/opt/gc.log -jar xxx.jar

我們這裏添加了日誌的收集
在這裏插入圖片描述
我們去對應目錄找一下日誌,裏面的參數我們都介紹過,這個不難看懂。
在這裏插入圖片描述
但是文件內容是非常非常多的,這樣一點點的看可能有點困難,我們一邊把文件下載下來,用GCViewer這個開源的工具來做這件事情。

GCViewer工具,輔助分析GC日誌文件 https://github.com/chewiebug/GCViewer
在這裏插入圖片描述
打開下載到本地的gc.log文件
在這裏插入圖片描述
再看右下角的信息,主要是一些彙總信息。各種數據的分析,比如平均,最大,最小等。
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
至於首頁的圖形,怎麼看,可以直接參考文檔:https://github.com/chewiebug/GCViewer

紅線意思是什麼等等 都寫的很詳細。

在這裏插入圖片描述
下面看一下jstat 動態監控GC統計信息,採用的格式是間隔1000毫秒統計一次,每10行數據後輸出列標題

jstat -gc -h10 $(jcmd | grep "demo-0.0.1-SNAPSHOT.jar" | awk '{print $1}') 1000

裏面的參數,我們說過了,參考上一篇文章【JVM實戰】基於JDK命令行工具的監控
在這裏插入圖片描述

下面看一下切換垃圾收集器或者調整垃圾收集器參數相關信息:

垃圾收集器 Parallel參數調優

這是JDK默認的收集器–吞吐量優先

參數 說明
-XX:+UseParallelGC 新生代使用並行回收收集器
-XX:+Use ParalleloldGC 老年代使用並行回收收集器
-XX:ParallelGCThreads 設置用於垃圾回收的線程數
-XX:+UseAdaptiveSizePolicy 打開自適應GC策略

自適應GC策略是指自動調整分代分區的大小。UseAdaptiveSizePolicy自適應默認開啓。

垃圾收集器CMS參數調優

關於CMS

  • 響應時間優先2
  • Parallel gc無法滿足應用程序延遲要求時再考慮使用CMS垃圾收集器。
  • 新版建議用G1垃圾收集器

在這裏插入圖片描述
垃圾收集器G1參數調優

關於G1:

  • 兼顧吞吐量和響應時間
  • 超過50%的Java堆被實時數據佔用。
  • 建議大堆(大小約爲6GB或更大)
  • 且GC延遲要求有限的應用(穩定且可預測的暫停時間低於0.5秒)。
    在這裏插入圖片描述

運行時JIT編譯器優化參數

JIT編譯指的是字節碼編譯爲本地代碼(彙編)執行,只有熱點代碼纔會編譯爲本地代碼。解釋器執行節約內存,反之可以使用編譯執行來提升效率

在這裏插入圖片描述
最後由於版本不斷更新,JVM參數和具體說明,建議需要時參考 oracle官網的手冊。

說實話,如果沒有一個具體的線上場景,很難去演示調優的過程,這裏能做到的就是,給出調優的思路、相關工具的使用,以及調優用到的參數信息。

參數的調整多少都會對JVM的運行有影響,比如 Parallel參數調優中-XX:ParallelGCThreads設置線程的數量,這個在不同配置的服務器上測試得到的結果會有差別,你可以在自己服務器上試試看。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章