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 ~]#

我这里选择的版本:openjdk-jdk-shenandoah-linux-x86_64-server-release-gcc10-glibc2.31.tar.xz

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都很明显!
一个程序员最重要的能力是:写出高质量的代码!!
有道无术,术尚可求也,有术无道,止于术。
无论你是年轻还是年长,所有程序员都需要记住:时刻努力学习新技术,否则就会被时代抛弃!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/232702.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Qt Creator设置IDE的字体、颜色、主题样式

Qt是一款开源的、跨平台的C开发框架&#xff0c;支持Windows、Linux、Mac系统&#xff0c;从1995发布第一版以来&#xff0c;发展迅猛&#xff0c;最开始是用于Nokia手机的Symbian(塞班)系统和应用程序开发&#xff0c;现在是用于嵌入式软件、桌面软件(比如WPS、VirtualBox)、A…

Tomcat部署开源站点JPress

前言 JPress使用Java开发&#xff0c;是我们常见的开源博客系统。JPress是一个开源的WordPress插件&#xff0c;它提供了一个简单而强大的方式来创建企业级站点。该插件包括许多特性&#xff0c;例如主题定制、页面构建器、性能优化、SEO、安全、电子商务和社交媒体整合等。使用…

Python实战演练之python实现神经网络模型算法

python实现神经网络模型算法 今天&#xff0c;厾罗和大家分享用Python实现神经网络模型算法&#xff0c;仅用于技术学习交流。 实现技巧 1.导入依赖库 主要是安装相关的依赖库。本文实现的环境为&#xff1a;python 3.7。 from __future__ import division import math …

【数值计算方法(黄明游)】迭代法的一般形式与收敛性定理

一、向量、矩阵范数与谱半径 【数值计算方法&#xff08;黄明游&#xff09;】解线性代数方程组的迭代法&#xff08;一&#xff09;&#xff1a;向量、矩阵范数与谱半径【理论到程序】 1. 向量范数 l 1 l_1 l1​ 范数&#xff08;曼哈顿范数&#xff09;&#xff1a; ∣ ∣…

MybatisPlus集成baomidou-dynamic,多数据源配置使用、MybatisPlus分页分组等操作示例

文章目录 MybatisPlus特性MybatisPlus支持数据库MybatisPlus 架构多数据源应用场景pom配置示例代码 MybatisPlus特性 无侵入&#xff1a;只做增强不做改变&#xff0c;引入它不会对现有工程产生影响&#xff0c;如丝般顺滑 损耗小&#xff1a;启动即会自动注入基本 CURD&#…

MySQL深入——8

Order by语句是如何工作的&#xff1f; 首先我们来创建一个表 CREATE TABLE t (id int(11) NOT NULL,city varchar(16) NOT NULL,name varchar(16) NOT NULL,age int(11) NOT NULL,addr varchar(128) DEFAULT NULL,PRIMARY KEY (id),KEY city (city) ) ENGINEInnoDB; 全字段…

JVS低代码表单引擎:数据校验与处理的先锋

随着信息技术的迅速发展&#xff0c;数据校验与处理已经成为了各类应用中不可或缺的一环。尤其是在涉及敏感信息&#xff0c;如密码处理时&#xff0c;其安全性和准确性显得尤为重要。JVS低代码表单引擎提供了强大的文本组件触发逻辑校验功能&#xff0c;它能够在用户填写数据的…

Python数据科学视频讲解:数据清洗、特征工程和数据可视化的注意事项

1.6 数据清洗、特征工程和数据可视化的注意事项 视频为《Python数据科学应用从入门到精通》张甜 杨维忠 清华大学出版社一书的随书赠送视频讲解1.6节内容。本书已正式出版上市&#xff0c;当当、京东、淘宝等平台热销中&#xff0c;搜索书名即可。内容涵盖数据科学应用的全流程…

【calcitonin ; 降钙素 ;降钙素原】

Parathyroid_Hormone -甲状旁腺激素 PTH &#xff1b; 特立帕肽&#xff1b;

【小米电脑管家】安装使用教程--非小米电脑

安装说明功能体验下载资源 Xiaomi HyperOS发布后&#xff0c;小米妙享电脑端独立版本也走向终点&#xff0c;最新的【小米电脑管家】将会内置妙享实现万物互联。那么本篇文章将分享非小米电脑用户如何绕过设备识别验证安装使用【小米电脑管家】实现万物互联 安装说明 1.解压文…

.NET Core 依赖注入 Microsoft.Extensions.DependencyInjection

文章目录 前言什么是依赖注入C# 使用依赖注入框架介绍 Microsoft.Extensions.DependencyInjectionNuget安装简单单例使用打印结果 自动装配举例自动装配测试用例打印结果自动装配执行顺序测试用例有歧义构造函数渐进式构造函数循环依赖 自动装配结论 手动装配手动注入别名注入 …

深入解析Spring Boot中的注解@PathVariable、@RequestParam、@RequestBody的正确使用

文章目录 1. 引言2. PathVariable&#xff1a;处理路径变量2.1 简介2.2 使用示例 3. RequestParam&#xff1a;处理请求参数3.1 简介3.2 使用示例 4. RequestBody&#xff1a;处理请求体4.1 简介4.2 使用示例 5. 多个注解的组合使用6. 参数绑定的原理6.1 HandlerMethodArgument…

亚马逊运营推荐数仓项目实战

亚马逊运营推荐数仓项目实战 项目技术栈 HadoopSpark (Python)Scala SparkSQLSparkStreaming MongoDB Redis Kafka Flume ( SpringMVC vue) 1 项目介绍 1.1 项目系统架构 项目以推荐系统建设领域知名的经过修改过的中文亚马逊电商数据集作为依托&#xff0c;以某电商…

Kubersphere应用【二】Docker安装

一、Docker安装 1.下载Docker安装包 【地址】Index of linux/static/stable/x86_64/ 2.上传至服务器 # 解压文件 tar -xvf docker-20.10.10.tgz# 将docker 目录中的所有文件复制至/usr/bin/目录下 cp docker/* /usr/bin 3.配置docker.service文件 vim /usr/lib/systemd/sy…

分割算法-大津算法

分割算法-大津算法 一、什么是大津算法二、算法原理三、公式推导四、代码五、算法适用性 大津算法介绍以及C函数代码实现。 一、什么是大津算法 大津算法&#xff08;Otsu&#xff09;由日本学者大津展之在1979年提出&#xff0c;又称最大类间方差法。此法求得的阈值&#xff…

git标签的管理与思考

git 标签管理 git 如何打标签呢&#xff1f; 标签是什么? 标签 相当于一个 版本管理的一个贴纸&#xff0c;随时 可以通过标签 切换到 这个版本的状态 &#xff0c; 有人可能有疑问 git commit 就可以知道 代码的改动了&#xff0c; 为啥还需要标签来管理呢&#xff1f; …

C++包管理利器CPM

C包管理利器CPM 一、介绍 CPM.cmake is a cross-platform CMake script that adds dependency management capabilities to CMake. It’s built as a thin wrapper around CMake’s FetchContent module that adds version control, caching, a simple API and more. CPM.cma…

四:爬虫-Cookie与Session实战

四&#xff1a;Cookie与Session实战 ​ 在浏览网站的过程中&#xff0c;我们经常会遇到需要登录的情况&#xff0c;有些页面只有登录之后才可以访问。在登录之后可以连续访问很多次网站&#xff0c;但是有时候过一段时间就需要重新登录。还有一些网站&#xff0c;在打开浏览器…

Uniapp软件库全新带勋章功能(包含前后端源码)

源码介绍&#xff1a; Uniapp开发的软件库全新带勋章功能&#xff0c;搭建好后台 在前端找到 util 这个文件 把两个js文件上面的填上自己的域名&#xff0c;电脑需要下载&#xff1a;HBuilderX 登录账号 没有账号就注册账号&#xff0c; 然后上传文件&#xff0c;打包选择 “…

轻量封装WebGPU渲染系统示例<43>- 材质组装流水线(MaterialPipeline)之灯光和阴影(源码)

目标: 数据化&#xff0c;模块化&#xff0c;自动化 备注: 从这个节点开始整体设计往系统规范的方向靠拢。之前的都算作是若干准备。所以会和之前的版本实现有些差异。 当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/feature/material/src/voxgpu/sa…