JVM Optimization Learning(六)

目錄

一、JVM?Optimization

1、Shenandoah

Shenandoah的使用方法

2、ZGC

ZGC的版本更迭

ZGC的使用方法

ZGC的參數設置

3、JMH測試GC性能


一、JVM?Optimization

1、Shenandoah

????????Shenandoah是由Red Hat開發的一款低延遲的垃圾收集器,Shenandoah并發執行大部分GC工作,包括并發的整理,堆大小對STW的時間基本沒有影響

Shenandoah的使用方法

1、下載:Shenandoah只包含在OpenJDK中,默認不包含在內,需要單獨構建,可以直接下載構建好的。

Shenandoah下載地址

下載選擇方式如下:?

1、{aarch64,arm32-hflt,mipsel,mips64el,ppc64le,s390x,x86_32,x86_64}:架構,linux中使用arch命令選擇對應的架構。

[root@localhost ~]# arch
x86_64

2、{server,zero}:虛擬機類型,選擇server,包含所有GC功能

3、{release,fastdebug,Slowdebug,optimization}:不同的優化級別,選擇release,性能最高。

4、{gcc*glibc*,msvc*}:編譯期版本,選擇較高的版本性能好一些,如果兼容性有問題,(無法啟動)選擇較低的版本。--glibc版本選擇

[root@localhost ~]# ldd --version
ldd (GNU libc) 2.17
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.
[root@localhost ~]#

centos版本低。重新安裝ubuntu操作系統22.4.3版本

root@admin:~# ldd --version
ldd (Ubuntu GLIBC 2.35-0ubuntu3.5) 2.35
Copyright (C) 2022 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.
root@admin:~#

我這里選擇的版本:openjdk-jdk-shenandoah-linux-x86_64-server-release-gcc10-glibc2.31.tar.xz

root@admin:/usr/java# java -version
openjdk version "22-testing" 2024-03-19
OpenJDK Runtime Environment (build 22-testing-builds.shipilev.net-openjdk-jdk-shenandoah-b171-20231209)
OpenJDK 64-Bit Server VM (build 22-testing-builds.shipilev.net-openjdk-jdk-shenandoah-b171-20231209, mixed mode, sharing)

2、配置。將OpenJDK配置到環境變量中,使用java -version進行測試。打印出如下內容代表成功。

3、添加參數,運行Java程序

-XX:+UseShenandoahGC 開啟Shenandoah GC

-Xlog:gc 打印GC日志

2、ZGC

ZGC文章

The Z Garbage Collector (ZGC) is a scalable low latency garbage collector. ZGC performs 
all expensive work concurrently, without stopping the execution of application threads 
for more than a millisecond. It is suitable for applications which require low latency.
Pause times are independent of the heap size that is being used. ZGC works well with 
heap sizes from a few hundred megabytes to 16TB. ZGC was initially introduced as an experimental feature in JDK 11, and was declared 
Production Ready in JDK 15. In JDK 21 was reimplemented to support generations.Z垃圾收集器(ZGC)是一種可擴展的低延遲垃圾收集器。ZGC執行所有昂貴的工作都是并發的,而不會停止
應用程序線程的執行持續超過一毫秒。它適用于需要低延遲的應用程序。暫停時間與正在使用的堆大小無關。
ZGC與堆大小從幾百兆字節到16TB。
ZGC最初是作為JDK 11中的一個實驗特性引入的,并聲明JDK 15中的生產就緒。JDK中重新實現了21,以支持幾代人。

? ? ? ? ZGC(Z Garbage Collector)是一款基于Region內存布局的,暫時不設分代的,使用了讀屏障、顏色指針等技術來實現可并發的,采用標記-整理算法的,以低延遲為首要目標的一款垃圾收集器。

????????ZGC是一種可擴展的低延遲垃圾回收器。ZGC在垃圾回收過程中,STW的時間不會超過一毫秒,適合需要低延遲的應用。支持幾百兆到16TB的堆大小,堆大小對STW的時間基本沒有影響。

????????ZGC降低了停頓時間,能降低接口的最大耗時,提升用戶體驗。但是吞吐量不佳,所以如果Java服務比較關注QPS(每秒的查詢次數),那么G1是比較不錯的選擇。

內存布局

????????跟G1類似,ZGC的堆內存也是基于Region來分布。不同的是,ZGC的Region支持動態地創建和銷毀,并且Region的大小不是固定的,包括三種類型的Region:

Smail Region:2MB,主要用于放置小于256KB的小對象。

Medium Region:32MB,主要用于放置大于等于256KB小于4MB的對象。

Large Region:N *?2MB,這個類型的Region是可以動態變化的,不過必須是2MB的整數倍,最小支持4MB,每個Large Region只放置一個大對象,并且是不會被重分配的。

顏色指針

顏色指針,如下圖所示,是ZGC的核心設計之一。以前的垃圾回收器的GC信息都保存在對象頭中,而ZGC的GC信息保存在指針中。

每個對象有一個64位指針,這64位被分為:

????????18位:預留給以后使用。

????????1位:Finalizable標識。

????????1位:Remapped標識,是否進入了重分配集(即被移動過)。

????????1位:Marked1標識,簡稱M1。

????????1位:Marked0標識,和上面的Marked1都是用于輔助GC。簡稱M0。

????????42位:對象的地址(所以它可以支持2^42=4T內存)。

垃圾收集過程

大概分為4個階段:并發標記,并發預備重分配,并發重分配,并發重映射。

????????并發標記(Concurrent Mark):與G1一樣,并發標記是遍歷對象,做可達性分析的階段。前后也要經過類似G1的初始標記、最終標記的短暫停頓。與G1不同的是,ZGC的標記是在指針上而不是在對象上進行的,標記階段會更新顏色指針的M0/M1標志位。

????????并發預備重分配(Concurrent Prepare for Relocate):這個階段根據特定的查詢條件統計出本次收集過程要清理哪些Region,將這些Region組成重分配集(Relocate Set)。重分配集與G1收集器的回收集(Collection Set)還是有區別的,ZGC劃分Region的目的并非為了像G1那樣做收益優先的增量回收。相反,ZGC每次回收都會掃描所有的Region。

????????并發重分配(Concurrent Relocate):該階段是ZGC執行過程中的核心階段,這個過程要把重分配集中的存活對象復制到新的Region上,并為重分配集中的每個Region維護一個轉發表(Forward Table),記錄從舊對象到新對象的轉向關系。得益于顏色指針的支持,ZGC收集器能僅從引用上就明確得知一個對象是否處于重分配分配集之中,如果用戶線程此時并發訪問了位于重分配集中的對象,這次訪問將被讀屏障所截獲,然后立即根據Region上的轉發表記錄將訪問轉發到新復制的對象上,并同時修正更新該引用的值,使其直接指向新對象,ZGC的這種行為稱作指針的“自愈”能力。

????????并發重映射(Concurrent Remap):該階段所做的主要是修正整個堆中指向重分配集中舊對象的所有引用。但是ZGC的并發重映射并不是必須要“迫切”去完成的任務。因為即使是舊引用,它也是可以自愈的,最多只是第一次使用時多一次轉發和修正操作。因此,ZGC很巧妙的將并發重映射階段要做的工作,合并到了下一次GC中的并發標記階段里去完成,反正它們都是要遍歷對象,這樣就節省了一次遍歷的開銷。一旦所有的指針被修正之后,原來記錄新舊關系的轉發表就可以釋放掉了。

ZGC的版本更迭

? ? ? ? 2018年JDK11,實驗版本。2019年JDK12-13,并行類的卸載AArch64架構支持。

? ? ? ? 2020年JDK14-15,windows & MacOS支持第一個正式版本。

? ? ? ? 2021年JDK16-17,亞毫秒級最大暫停時間并行線程數的自動計算。

? ? ? ? 2023年JDK21,支持分代年齡。

ZGC的使用方法

????????OracleJDK和OpenJDK中都支持ZGC,阿里的DragonWell龍井JDK也支持ZGC但屬于其自行對OpenJDK11的ZGC進行優化的版本。

????????建議使用JDK17之后的版本,延遲較低同時無需手動配置并行線程數

分代ZGC添加參數啟用:-XX:+UseZGC -XX:+ZGenerational

非分代ZGC通過命令行選項啟用:-XX:+UseZGC

ZGC的參數設置

需要設置的參數:

-Xmx值最大堆內存大小

????????這是ZGC最重要的一個參數,必須設置。ZGC在運行過程中會使用一部分內存來處理垃圾回收,所以盡量保證堆中有足夠的空間。設置多少值取決于對象分配的速度,根據測試情況來決定。

可以設置的參數

-XX:SoftMaxHeapSize=值

????????ZGC會盡量保持堆內存小于該值,這樣在內存靠近這個值時會盡早地進行垃圾回收,但是依然有可能會超過該值。例如:-Xmx5g -XX:SoftMaxHeapSize=4g 這個參數設置,ZGC會盡量保證堆內存大小4GB,最多不會超過5GB。

3、JMH測試GC性能

pom

<properties><java.version>21</java.version>
</properties><dependency><groupId>org.openjdk.jmh</groupId><artifactId>jmh-core</artifactId><version>1.37</version>
</dependency>
<dependency><groupId>org.openjdk.jmh</groupId><artifactId>jmh-generator-annprocess</artifactId><version>1.37</version>
</dependency>

測試代碼:

package com.lwz;import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;//執行5輪預熱,每次持續2秒
@Warmup(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS)
//輸出毫秒單位
@OutputTimeUnit(TimeUnit.MILLISECONDS)
//統計方法執行的平均時間
@BenchmarkMode(Mode.AverageTime)
//java -jar xxx.jar -rf json
@State(Scope.Benchmark)
public class JavaGc {//每次測試對象大小4KB和4M@Param({"4", "4096"})int perSize;private void test(Blackhole blackhole) {//每次循環創建堆內存60%對象 JMX獲取到Java運行中的實時數據MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();MemoryUsage heapMemoryUsage = memoryMXBean.getHeapMemoryUsage();//獲取到剩余的堆內存大小long heapSize = (long) ((heapMemoryUsage.getMax() - heapMemoryUsage.getUsed()) * 0.6);//計算循環的次數long size = heapSize / (1024L * perSize);for (int i = 0; i < 4; i++) {List<byte[]> list = new ArrayList<>((int) size);for (int j = 0; j < size; j++) {list.add(new byte[1024 * perSize]);}blackhole.consume(list);}}@Benchmark@Fork(value = 1,jvmArgsAppend = {"-Xms4g","-Xmx4g","-XX:+UseSerialGC"})public void serialGc(Blackhole blackhole){test(blackhole);}@Benchmark@Fork(value = 1,jvmArgsAppend = {"-Xms4g","-Xmx4g","-XX:+UseParallelGC"})public void parallelGc(Blackhole blackhole){test(blackhole);}@Benchmark@Fork(value = 1,jvmArgsAppend = {"-Xms4g","-Xmx4g"})public void g1(Blackhole blackhole){test(blackhole);}@Benchmark@Fork(value = 1,jvmArgsAppend = {"-Xms4g","-Xmx4g","-XX:+UseShenandoahGC"})public void shenandoahGc(Blackhole blackhole){test(blackhole);}@Benchmark@Fork(value = 1,jvmArgsAppend = {"-Xms4g","-Xmx4g","-XX:+UseZGC"})public void zGc(Blackhole blackhole){test(blackhole);}@Benchmark@Fork(value = 1,jvmArgsAppend = {"-Xms4g","-Xmx4g","-XX:+UseZGC","-XX:+ZGenerational"})public void zGcGenerational(Blackhole blackhole){test(blackhole);}public static void main(String[] args) throws RunnerException {Options opt = new OptionsBuilder().include(JavaGc.class.getSimpleName()).forks(1).build();new Runner(opt).run();}
}

JVM Optimization Learning(五)

再小的努力,乘以365都很明顯!
一個程序員最重要的能力是:寫出高質量的代碼!!
有道無術,術尚可求也,有術無道,止于術。
無論你是年輕還是年長,所有程序員都需要記住:時刻努力學習新技術,否則就會被時代拋棄!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/211899.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/211899.shtml
英文地址,請注明出處:http://en.pswp.cn/news/211899.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

機器人純阻抗控制接觸剛性環境(阻尼影響因素)

問題描述 在機器人學中&#xff0c;阻抗控制是一種常用的控制策略&#xff0c;用于管理機器人在與環境交互時的運動和力。阻抗控制背后的關鍵概念是將環境視為導納&#xff0c;而將機器人視為阻抗。 純阻抗控制接觸剛性環境時&#xff0c;機器人的行為方式主要受其阻抗參數的…

數據結構和算法專題---6、定時算法與應用

本章我們會對定時算法做個簡單介紹&#xff0c;包括常用的定時算法&#xff08;最小堆、時間輪&#xff09;的概述、實現方式、典型場景做個說明。 概述 系統或者項目中難免會遇到各種需要自動去執行的任務&#xff0c;實現這些任務的手段也多種多樣&#xff0c;如操作系統的…

【C++】使用“/**/“進行注釋的好處

2023年12月10日&#xff0c;周日晚上 我今天下午看Google Chrome的源碼時&#xff0c;才發現"/**/"原來還能這么用 使用"/**/"的好處就是&#xff0c;可以在任何地方進行注釋&#xff0c;哪怕是參數列表 void CircularWindow::enterEvent(QEvent *event/…

【Python】判斷域名是否合法

python判斷域名是否合法|校驗域名 域名以點號分隔成多個字符串。單個字符串由各國文字的特定字符集、字母、數字、連字符&#xff08;-&#xff09;組成&#xff0c;字母不區分大小寫&#xff0c;連字符&#xff08;-&#xff09;不得出現在字符串的頭部或者尾部。單個字符串長…

GitHub Enterprise Server 添加代碼安全、自動化功能

GitHub的軟件更新用于管理私有服務器上的存儲庫&#xff0c;具有GitHub容器注冊訪問、Dependabot安全警報和更新以及可重用工作流的特性。 GitHub Enterprise Server 3.5是GitHub用于托管和管理私有服務器上存儲庫的最新版本&#xff0c;它引入了新的代碼安全特性&#xff0c;新…

Helm 常用運維命令

原理參考 ## https://blog.csdn.net/knight_zhou/article/details/122079292 常用運維命令 helm search: ??搜索charthelm pull: ???下載chart到本地目錄查看helm install: ??上傳chart到Kuberneteshelm list: ????列出已發布的chart

【開源】基于Vue和SpringBoot的車險自助理賠系統

項目編號&#xff1a; S 018 &#xff0c;文末獲取源碼。 \color{red}{項目編號&#xff1a;S018&#xff0c;文末獲取源碼。} 項目編號&#xff1a;S018&#xff0c;文末獲取源碼。 目錄 一、摘要1.1 項目介紹1.2 項目錄屏 二、功能模塊2.1 數據中心模塊2.2 角色管理模塊2.3 車…

Maven基礎

目錄 Maven坐標 坐標簡介 主要組成 Maven依賴管理 配置依賴 依賴簡介 配置依賴 依賴傳遞 依賴傳遞簡介 排除依賴 依賴范圍 生命周期 生命周期簡介 執行指定生命周期 Maven坐標 坐標簡介 Maven中的坐標是資源的唯一標識&#xff0c;通過該坐標可以唯一定位資…

Redis交互速度慢,CPU占用100%,集群方案,報錯等問題

后續補充結論 仔細查看前輩們堆的代碼中發現居然調用了大量key*查詢&#xff0c;導致走的遍歷非常慢&#xff01;因為這相當與全部數據量遍歷&#xff0c;即這個原因導致了查詢速度與數據量成正比&#xff0c;推測也是CPU占用高的元兇&#xff1b;即使加上key前綴再匹配*也會走…

Python開發運維:Python調用K8S API實現資源管理

目錄 一、實驗 1.Python操作K8S API獲取資源 2.Python操作K8S API創建deployment資源 3.Python操作K8S API刪除k8s資源 4.Python操作K8S API修改k8s資源 5.Python操作K8S API查看k8s資源 二、問題 1.Windows11安裝kubernetes報錯 2.Python通過調用哪些方法實現Pod和De…

在SpringData JPA 中實現對持久層的操作

1.導入依賴 hibernate 這個依賴自帶實現JPA接口 <dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><depen…

TCP三次握手、四次揮手及狀態轉換詳解

1.什么是TCP協議&#xff1f; 傳輸控制協議&#xff08;TCP&#xff0c;Transmission Control Protocol&#xff09;是一種面向連接的、可靠的、基于字節流的傳輸層通信協議&#xff0c;位于網絡OSI七層模型的第四層&#xff0c;IP協議一起工作&#xff0c;TCP層是位于IP層之上…

(Spring學習07)Spring之啟動刷新過程源碼解析

概述 通常&#xff0c;我們說的Spring啟動&#xff0c;就是構造ApplicationContext對象以及調用refresh()方法的過程。 首先&#xff0c;Spring啟動過程主要做了這么幾件事情&#xff1a; 構造一個BeanFactory對象解析配置類&#xff0c;得到BeanDefinition&#xff0c;并注冊…

CrystalDiskInfo中文版(硬盤檢測工具) v9.1.1.0 綠色漢化版-供大家學習研究參考

更新內容 重新支持三星SATA SSD壽命報告 增加對ZHITAI SC001的支持 新增SK hynix Gold S31支持 增加了KLEVV NEO N610的支持。 改進的Micron/Crucial SATA SSD支持 已更改 卸載程序將顯示一個確認對話框&#xff0c;用于刪除設置。 強大功能 1.擁有多國語言&#xff0c;…

27 動態規劃解最大子序和

問題描述&#xff1a;給定一個整數數組nums&#xff0c;找到一個具有最大和的連續子數組(子數組最少含有一個元素)&#xff0c;返回其最大和。 動態規劃求解&#xff1a;定義dp[i]表示以i元素為結尾的最大和&#xff0c;如果dp[i-1]小于零的話&#xff0c;dp[i]nums[i],否則dp…

React-hook-form-mui(三):表單驗證

前言 在上一篇文章中&#xff0c;我們介紹了react-hook-form-mui的基礎用法。本文將著重講解表單驗證功能。 react-hook-form-mui提供了豐富的表單驗證功能&#xff0c;可以通過validation屬性來設置表單驗證規則。本文將詳細介紹validation的三種實現方法&#xff0c;以及如何…

ts中type和interface類型聲明的區別

1. 寫法上 type 使用關鍵字 type 進行聲明。 interface 使用關鍵字 interface 進行聲明。 // 使用 type type MyType {param: string; };// 使用 interface interface MyInterface {param: string; }2. 可合并性 interface 具有可合并性&#xff0c;允許在同一作用域內多次…

045:Vue讀取本地上傳JSON文件,導出JSON文件方法

第045個 查看專欄目錄: VUE ------ element UI 專欄目標 在vue和element UI聯合技術棧的操控下&#xff0c;本專欄提供行之有效的源代碼示例和信息點介紹&#xff0c;做到靈活運用。 &#xff08;1&#xff09;提供vue2的一些基本操作&#xff1a;安裝、引用&#xff0c;模板使…

jquery手寫廣告輪播圖,無限循環功能

說明 在很多情況下&#xff0c;我們都需要開發廣告輪播圖&#xff0c;當我們進行頁面的功能開發時&#xff0c;采用輪播圖來實現也行&#xff0c;但是很多情況下&#xff0c;我們只需要簡單的控制輪播循環輪播展示即可&#xff0c;所以用jq開開發廣告輪播波&#xff0c;自定義…

spring更加松散的獲取bean的方式ObjectProvider

概述 ObjectProvider直譯就是對象提供者; 平時從spring中獲取bean都是調用beanFactory.getBean()方法&#xff0c;如果bean不存在則會直接拋異常; 從spring 4.3開始引入了org.springframework.beans.factory.ObjectProvider接口,其提供了若干的方法&#xff0c;可以更松散的…