十九.升职加薪系列-JVM优化-解决JVM性能瓶颈的JIT即时编译器

前言

在很多年以前,做C或者C++的程序员经常说Java语言的运行速度不如C或C++,Java运行速度慢主要是因为它是解释执行的,而C或C++是编译执行的,解释执行需要通过JVM虚拟机将字节码实时翻译成机器码(边翻译边执行),才能运行在操作系统上,这个过程会比编译执行慢。

但现在再说这个结论就不太对了,随着JIT即时编译技术的发展,性能差距正在逐步缩小,甚至在某些情况下,执行速度是优于C或C++的。

一.为什么出现JIT

1.JVM代码执行流程

我们编写的Java程序是由以.java结尾的源文件,通过javac指令编译为由.class结尾的字节码文件,而字节码文件被加载进入JVM后,是通过JVM的解释器逐条读取字节码,并将其翻译成对应平台的机器指令执行。虽然解释执行具有跨平台性好、启动速度快的特点,但其执行效率相对较低。因为每次执行字节码时,都需要经过解释器的翻译过程,这增加了额外的开销。特别是在执行循环、递归等热点代码时,性能瓶颈尤为明显。
在这里插入图片描述

2.JIT技术的引入

为了解决这一性能瓶颈,JVM引入了JIT即时编译器技术。JIT技术能够在程序运行时动态地将字节码编译成本地机器码,并且根据程序的实际运行情况对机器码进行优化,从而提高程序的执行效率。

当某些方法或代码块(它们都对应特定的字节码)被频繁调用时,这部分代码就被视为热点代码。JVM虚拟机会针对性的对这部分’热点代码进行优化编译,将它们从字节码转换为本地机器码,然后将优化后的本地机器码缓存起来,后续再执行时可以直接从缓存中获取并运行,无需再次编译。JVM提供了一个参数“-XX:ReservedCodeCacheSize”,用来限制 CodeCache 的大小。也就是说,JIT 编译后的代码都会放在 CodeCache 里。

在这里插入图片描述
而热点代码由热点探测进行发现,热点探测基于计数器,JVM虚拟机会为每个方法建立对应的计数器,统计方法的执行次数、方法内的循环次数等,如果计数器超过指定阈值,则标识其为热点代码。

二.认识JIT即时编译器

1.C1和C2编译器

主流的HotSpot虚拟机内置了两个JIT编译器:C1(Client Compiler)编译器和C2(Server Compiler)编译器,C1和C2编译器在优化方面有不同的侧重点:C1侧重编译速度,C2侧重深度优化

  • Client Compiler(C1):针对客户端应用程序,优化启动时间,以较少的编译优化来实现更快的编译速度。
  • Server Compiler(C2):C2编译器侧重于深度优化,与C1正好相反,C2编译器的编译时间较长,但优化的程度较高。C2的优化策略比较深度,会进行更高级的优化,比如逃逸分析等,C2编译器编译的代码的执行速度通常比C1编译器快。

C2编译器由于深度优化代码过于复杂,已经很难维护了,从JDK 10开始,Graal编译器已经代替了C2编译器,与C1编译器协同工作
在这里插入图片描述

2.JIT优化技术-热点探测

JIT(Just-In-Time)优化技术是一种在程序运行时动态地将部分代码编译成机器代码,以提高程序执行效率和性能的技术。这种技术广泛应用于动态语言、虚拟机和一些解释型语言的执行环境中。JIT优化技术主要包括:热点探测,编译优化,内联优化,挑分析等。

热点检测:热点检测是指在程序运行时,通过监测代码的执行情况,识别出被频繁执行的代码块或方法,即热点代码。通过计数器记录代码块或方法的执行次数,当某个代码块的执行次数超过一定阈值时,认为它是热点代码。

虚拟机为每个方法准备了两类计数器:方法调用计数器(Invocation Counter)和回边计数器(Back Edge Counter)。在确定虚拟机运行参数的前提下,这两个计数器都有一个确定的阈值,当计数器超过阈值溢出了,就会触发 JIT 编译。

方法调用计数器

用于统计方法被调用的次数,方法调用计数器的默认阈值在客户端模式下是 1500 次,在服务端模式下是 10000 次(我们用的都是服务端,java –version查询),可通过 -XX: CompileThreshold 来设定

回边计数器

用于统计一个方法中循环体代码执行的次数,在字节码中遇到控制流向后跳转的指令称为“回边”(Back Edge),该值用于计算是否触发 C1 编译的阈值,在不开启分层编译的情况下,在服务端模式下是10700。
回边计数器阈值 =方法调用计数器阈值(CompileThreshold)×(OSR比率(OnStackReplacePercentage)-解释器监控比率(InterpreterProfilePercentage)/100 , 通过 java -XX:+PrintFlagsFinal –version查询相关参数:

在这里插入图片描述在这里插入图片描述其中OnStackReplacePercentage默认值为140,InterpreterProfilePercentage默认值为33,如果都取默认值,那Server模式虚拟机回边计数器的阈值为10700. 回边计数器阈值 =10000×(140-33)=10700

3.方法内联

将函数调用处的代码直接插入到调用点,减少函数调用的开销。

// 方法内联
public int xx() {int num1 = 111;int num2 = 222;// 等价于 ->  sum = num1 + num2int sum = add(num1, num2);return sum;
}public int add(int num1, int num2) {return num1 + num1;
}

在代码中,方法内联会将其中的add(num1, num2)方法转换为实际的num1 + num1,直接进行计算操作,避免了方法调用。

4.锁消除技术

如果在线程安全的情况下使用了一个线程安全的容器那么会导致性能降低,比如StringBuffer这样的类的append方法是有Synchronized同步锁使的性能底下

public void xx(){SpringBuffer s = new StringBuffer();s.append(...)
}

但实际上,在以上代码测试中,StringBuffer 和 StringBuilder 的性能基本没什么区别。这是因为在局部方法中创建的对象只能被当前线程访问,无法被其它线程访问,这个变量的读写肯定不会有竞争,这个时候 JIT 编译会对这个对象的方法锁进行锁消除。
使用StringBuffer和StringBuilder,我们把锁消除关闭—测试发现性能差别有点大

  • -XX:+EliminateLocks开启锁消除(jdk1.8默认开启,其它版本未测试)
  • -XX:-EliminateLocks 关闭锁消除

锁粗化

for( ... ){Synchronized(this){ ... }
}

锁粗化的作用:如果检测到同一个对象执行了连续的加锁和解锁的操作,则会将这一系列操作合并成一个更大的锁,从而提升程序的执行效率。

5.逃逸分析技术

大家常理解的对象分配是在堆中分配的,对象的引用变量通常在栈中,当方法结束栈销毁后,堆中对象失去引用后等待垃圾回收器回收。在某种情况下对象是可以在栈中分配的,也就是说当栈被销毁对象也会被销毁,这样的话大大减少了GC的回收成本。这种对象分配就是栈上分配,是否能在栈上分配需要使用逃逸分析算法进行计算。
在这里插入图片描述

逃逸分析的原理:分析对象动态作用域,当一个对象在方法中定义后,它不会被外部方法所引用(无法逃逸),那么这样的对象会被在栈中分配,因为该对象只是在当前方法中使用,如下:

public void jjjj(){for(... : 50000){xxx();}
}
public void xxx() {User user = new User();	//栈上分配user.name = "zhangsan";user.age = 18;//to do something
}

当然逃逸分析技术属于JIT的优化技术,所以必须要符合热点代码,JIT才会优化,另外对象如果要分配到栈上,需要将对象拆分(大对象放不下需要拆解),这种编译优化就叫做标量替换技术。

也就是说:要满足栈中分配需要满足2个条件,一是热点代码 ,而是标量替换。

  • -XX:+DoEscapeAnalysis开启逃逸分析(jdk1.8默认开启)
  • -XX:-DoEscapeAnalysis 关闭逃逸分析
  • -XX:+EliminateAllocations开启标量替换(jdk1.8默认开启)
  • -XX:-EliminateAllocations 关闭标量替换

三.总结

本篇文章介绍了JVM的JIT即时编译器,它解决了解释器在逐行解释性能差的问题,它通过对热点代码的探测,将热点代码编译后进行缓存,从而提高程序的执行性能。
而JIT的优化技术除了热点代码编译缓存外,还提供了方法内联,锁消除,逃逸分析等手段来提高程序性能。

文章结束喜欢的话请给个好评!!!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Rust 版本升级:rustup update stable 报错

Rust 版本升级 rustup update stable 报错 一、报错内容 error: could not download file from ‘https://static.rust-lang.org/dist/channel-rust-stable.toml.sha256’ to ‘/Users/xxx/.rustup/tmp/rv6vdfu3eupwo64m_file’: failed to make network request: error sendi…

【实战场景】@Transactional中使用for update的注意点

【实战场景】Transactional中使用for update的注意点 开篇词:干货篇:知识回顾注意点1.锁的范围和粒度:2.事务的隔离级别:3.死锁:4.性能影响:5.事务的边界:6.异常处理:7. 数据库和存储…

【漏洞复现】网神 SecGate 3600 防火墙 sys_export_conf_local_save 任意文件读取

免责声明: 本文内容旨在提供有关特定漏洞或安全漏洞的信息,以帮助用户更好地了解可能存在的风险。公布此类信息的目的在于促进网络安全意识和技术进步,并非出于任何恶意目的。阅读者应该明白,在利用本文提到的漏洞信息或进行相关测…

javaweb学习day5--《HTML篇》Springboot的模块创建、HTML的相关知识点详解

一、前言 从今天开始,就要启动后端的学习了,Springboot会贯穿到底,一定要跟着小编严谨的去搭建Springboot环境,依赖添加的过程可能需要2分钟左右,读者们要耐心等待一下,搭建好Springboot之后才算正式的开始…

算力革命:弹性租赁,解锁无限可能

华为创始人任正非曾在一场程序设计竞赛中说道,我们即将进入第四次工业革命,基础就是大算力。事实上,随着5G、人工智能等信息技术的迅猛发展,算力需求持续增长,但高昂的成本和快速的技术迭代让许多中小企业和个人开发者…

Covalent Network(CXT)通过社区投票将代币迁移并更名为 CXT,以推动人工智能更深层次的创新

专注于人工智能和 Web3 的模块化数据基础设施 Covalent Network(CXT)宣布,其治理提案已通过社区投票并顺利实施,即将原生代币 CQT 迁移为新的 CXT 代币,并部署至新的合约。这一关键性转变标志着 Covalent Network&…

springboot文达办公物资管理系统-计算机毕业设计源码51191

摘要 本文介绍了一种名为"文达办公物资管理系统"的基于JAVA语言、基于Springboot框架和MYSQL数据库开发的管理系统。该系统主要分为管理员和员工用户两个角色,以满足不同用户的需求。 对于管理员用户,系统提供了仪器设备管理、设备借用管理、设…

【大数据技术】换新电脑了,如何快速迁移MySQL到新电脑上(含程序+数据),这样既快速又高效,省去了“各种安装+各种配置+各种迁移数据”带来的麻烦和时间

【大数据技术】换新电脑了,如何快速迁移MySQL到新电脑上(含程序数据 背景步骤总结 背景 很久没有写博文了哦,最近我换了新的笔记本,于是需要在新笔记本电脑上搭建MySQL环境,因为我原电脑上是安装的MySQL解压版,故我想偷偷懒&…

可理解性评估:使用Google Gemini优化语音识别的意义保留

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

实验1 —— 安全策略的练习

实验拓扑图 实验要求 1.DMZ区内的服务器,办公区仅能在办公时间内(9:00-18:00)可以访问,生产区的设备全天可以访问; 2.生产区不允许访问互联网,办公区和游客区允许访问互联网 3.办公区…

动手学Avalonia:基于硅基流动构建一个文生图应用(一)

文生图 文生图,全称“文字生成图像”(Text-to-Image),是一种AI技术,能够根据给定的文本描述生成相应的图像。这种技术利用深度学习模型,如生成对抗网络(GANs)或变换器(T…

【Mac】Charles for Mac(HTTP协议抓包工具)及同类型软件介绍

软件介绍 Charles for Mac 是一款功能强大的网络调试工具,主要用于HTTP代理/HTTP监视器。以下是它的一些主要特点和功能: 1.HTTP代理:Charles 可以作为HTTP代理服务器,允许你查看客户端和服务器之间的所有HTTP和SSL/TLS通信。 …

金航标kinghelm宋仕强在介绍自己公司时说

金航标kinghelm宋仕强在介绍自己公司时说,金航标成立于2007年,成立地点在华强北雷圳大厦803室,后搬到华强北广业大厦24楼CD室,后搬迁到龙华展滔科技大厦C座C809和C817室,现在的办公地址为龙岗区坂田街道百瑞达大厦&…

PageDTO<T>,PageQuery,BeanUtils,CollUtils的封装

一、PageDTO<T> import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.fasterxml.jackson.annotation.JsonIgnore; import com.tianji.common.utils.BeanUtils; import com.tianji.common.utils.CollUtils; import com.tianji.common.utils.…

C#中的MD5摘要算法与哈希算法

文章目录 一、哈希算法基础二、MD5 算法原理三、MD5摘要算法四、哈希算法五、C#实现示例MD5算法示例哈希算法示例字符串MD5值对比 六、总结 一、哈希算法基础 哈希算法是一种单向密码体制&#xff0c;它将任意长度的数据转换成固定长度的字符串。这种转换是不可逆的&#xff0…

IDEA中配置代理,解决Codearts Snap登陆不了的问题

问题描述&#xff1a;在mac电脑中的idea中安装了华为的codearts snap插件&#xff0c;一直登录不了&#xff0c;账号是没问题的&#xff0c;后来我怀疑是我的代理有问题&#xff0c;找到IDEA中的代理设置先是有这个问题“You have JVM property "https.proxyHost" se…

千呼新零售2.0分销商城视频介绍

千呼新零售2.0系统是零售行业连锁店一体化收银系统&#xff0c;包括线下收银线上商城连锁店管理ERP管理商品管理供应商管理会员营销等功能为一体&#xff0c;线上线下数据全部打通。 适用于商超、便利店、水果、生鲜、母婴、服装、零食、百货、宠物等连锁店使用。 详细介绍请…

Android初学者书籍推荐

书单 1.《Android应用开发项目式教程》&#xff0c;机械工业出版社&#xff0c;2024年出版2.《第一行代码Android》第二版3.《第一行代码Android》第三版4.《疯狂Android讲义》第四版5.《Android移动应用基础教程&#xff08;Android Studio 第2版&#xff09;》 从学安卓到用安…

【机器学习】支持向量机与主成分分析在机器学习中的应用

文章目录 一、支持向量机概述什么是支持向量机&#xff1f;超平面和支持向量大边距直觉 二、数据预处理与可视化数据集的基本信息导入必要的库加载数据集数据概况数据可视化特征对的散点图矩阵类别分布条形图平均面积与平均光滑度的散点图变量之间的相关性热图 三、模型训练&am…

在conda的环境中安装Jupyter及其他软件包

Pytorch版本、安装和检验 大多数软件包都是随Anaconda安装的&#xff0c;也可以根据需要手动安装一些其他软件包。 目录 创建虚拟环境 进入虚拟环境 安装Jupyter notebook 安装matplotlib 安装 pandas 创建虚拟环境 基于conda包的环境创建、激活、管理与删除http://t.cs…