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

news2025/3/1 22:32:21

前言

在很多年以前,做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 + num2
    int 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.coloradmin.cn/o/1917714.html

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

相关文章

ArcGIS Pro入门制图教程

地理信息系统 (GIS) 是一种使用地图显示和分析数据的方式。在本教程中,您将学习桌面 GIS 应用程序 ArcGIS Pro 的基础知识。 新加坡的一家旅行社希望制作一款宣传册,用于向游客介绍距离市中心热门目的地最近的火车站。该宣传册将与带有文本信息的地图相…

【Element-UI 表格表头、内容合并单元格】

一、实现效果&#xff1a; &#x1f970; 表头合并行、合并列 &#x1f970; &#x1f970; 表格内容行、合并列 &#x1f970; thead和tbody分别有单独的合并方法 二、关键代码&#xff1a; <el-table size"mini" class"table-th-F4F6FB" align&qu…

VUE_TypeError: Cannot convert a BigInt value to a number at Math.pow 解决方法

错误信息 TypeError: Cannot convert a BigInt value to a number at Math.pow vue 或 react package.json添加 "browserslist": {"production": ["chrome > 67","edge > 79","firefox > 68","opera >…

用神经架构搜索给LLM瘦身,模型变小,准确度有时反而更高

用神经架构搜索给 LLM 瘦身&#xff0c;同等准确度可让 LLaMA2-7B 模型大小降 2 倍。 大型语言模型&#xff08;LLM&#xff09;的一个主要特点是「大」&#xff0c;也因此其训练和部署成本都相当高&#xff0c;如何在保证 LLM 准确度的同时让其变小就成了非常重要且有价值的研…

SaaS模式的海外仓系统:有什么优势,理由是什么?

海外仓系统是海外仓使用频率最高的工具类系统&#xff0c;根据数据显示&#xff0c;超过84%的海外仓都会通过海外仓系统规划仓库管理。 然而&#xff0c;市场上存在许多不同的海外仓系统类型供大家选择&#xff0c;主要是分为两类&#xff1a;本地部署和saas模式。今天主要是和…

AI绘画何以突飞猛进? 从历史到技术突破, 一文读懂火爆的AI绘画发展史

前言 自从前段时间偶然间被当下AI绘画的水平震住之后&#xff08;超越一切的AI作画神器&#xff0c;和它创作的234个盔甲美女未来战士&#xff09; &#xff0c;作者深感当今AI绘画的飞速进展或许已远超所有人的预期。 而这里的前因后果&#xff0c;包括AI绘画的历史&#xff…

科研人必备!6个AI学术论文写作好帮手

人们都说一个新的人工智能时代已经到来&#xff0c;很多工作都将被这类机器人取代。不可否认的是&#xff0c;在学术界&#xff0c;有了 AI&#xff0c;科学研究人员将可以有更多时间专注在更有意义的任务上。科研人员可以利用 AI 工具分析大量数据、识别模式、做出决策&#x…

stm32h743 阿波罗v2 NetXduo http server CubeIDE+CubeMX

在这边要设置mpu的大小&#xff0c;要用到http server&#xff0c;mpu得设置的大一些 我是这么设置的&#xff0c;做一个参考 同样&#xff0c;在FLASH.ld里面也要对应修改&#xff0c;SECTIONS里增加.tcp_sec和 .nx_data两个区&#xff0c;我们用ram_d2区域去做网络&#xff…

电商IP分类及其应用是什么?

在现代电商运营中&#xff0c;IP地址不仅是网络通信的基础&#xff0c;也扮演着关键的角色&#xff0c;支持多种功能和应用场景。本文将介绍几种常见的电商IP分类&#xff0c;以及它们在电商领域中的具体应用。 1. 前台IP与后台IP 电商网站在运营过程中通常需要区分前台IP和后…

机器学习——L1 L2 范数 —>L1 L2正则化

1、L1范数和L2范数是机器学习和数据分析中经常使用的两种范数&#xff0c;它们之间存在多个方面的区别。 以下是关于L1范数和L2范数区别的详细解释&#xff1a; 一、定义差异 L1范数&#xff1a;也被称为曼哈顿范数&#xff0c;是向量元素的绝对值之和。对于一个n维向量x&am…

全网最全,保姆级Stable Diffusion系列入门使用教程(图生图、LoRA、提示词权重),建议收藏!

大家好&#xff0c;我是画画的小强 今天将给大家讲解 Stable Diffusion 入门使用教程的 图生图、LoRA和提示词权重的教程&#xff0c;如果你还没有使用或者安装SD&#xff0c;那么可以看看我的往期入门教程AI绘画『Stable Diffusion』面向小白的免费AI绘画工具&#xff1a;解压…

技术开发分享:商品详情APP原数据实时接口代码解析

商品详情app端原数据实时接口代码解析主要包括以下几个步骤&#xff1a; 获取商品ID&#xff1a;首先需要从淘宝的分享链接中提取商品ID&#xff0c;可以通过正则表达式匹配的方式获取。 构建请求URL&#xff1a;根据商品ID构建请求URL&#xff0c;通常包括淘宝的商品详情API地…

SAP HCM 如何知道标准程序有自定义增强代码 Configure Debugger Layer

导读 INTRODUCTION Configure Debugger Layer &#xff1a;今天分享下我在处理HCM业务中&#xff0c;如何通过debug的Configure Debugger Layer找到标准程序中的客制化的代码&#xff1f;也许在网上查看到很多找badi的方法或者其他的办法&#xff0c;但是这些办法比较繁琐&…

电脑数据恢复篇:如何从电脑中恢复已删除的照片

按下 Shift Delete 后后悔了&#xff1f;想要恢复已删除的照片&#xff1f;好吧&#xff0c;如果是这样的话&#xff0c;你来对地方了。在本文中&#xff0c;我们将讨论如何从 PC 中恢复已删除的文件。 自从摄影的概念被提出以来&#xff0c;人们就对它着迷。以前&#xff0c…

Windows下载及安装OpenSSL

文章目录 前言一、OpenSSL下载二、OpenSSL安装1.双击下载好的安装包2.选择【I accept the agreement】→ 点击【Next】3.选择OpenSSL安装的位置 → 点击【Next】4.点击【Next】5.点击【Next】6.点击【Install】安装OpenSSL7.等待安装8.取消勾选 → 点击【Finish】完成安装 三、…

优思学院|流水线生产为什么不是最高效的?

谈到工厂的生产模式&#xff0c;人们印象中可能会浮现出长长的流水线和密集的作业人员。在传统的大规模生产装配线上确实如此&#xff0c;强调的是标准化大规模生产&#xff0c;采用专职分工方式&#xff0c;生产线上的作业人员只做同一个简单的动作&#xff0c;以达到降低成本…

SSL 证书错误:如何修复以及错误发生的原因

SSL证书可以提升网站的可信度。然而&#xff0c;如果您的SSL证书出现错误&#xff0c;您可能会得到一个“不安全”的标签&#xff0c;这可能会导致访问者失去对您网站的信任并转向竞争对手。 本文将介绍SSL证书错误的原因及其对用户的潜在影响。随后&#xff0c;我们将提供详细…

实验7 数据查询(2)

一、实验目的 学习SQL语言的定义、操纵功能熟悉通过SQL语言对数据库进行查询操作&#xff0c;包括单表查询、多表查询、嵌套查询、集合查询 二、实验软件 MySQL三、实验内容和要求 给定四个关联表&#xff0c;其定义和数据加载如下&#xff1a; 学生表 Student create tab…

【信创国产化】Nacos 2.3.2连接达梦数据库

JeecgBoot 目前提供的nacos版本号 2.3.2已经支持与达梦数据库对接。 jeecg-boot/jeecg-server-cloud/jeecg-cloud-nacos项目默认加入了达梦驱动和yml配置。如果你是老代码&#xff0c;可以参考下面的步骤手工集成 项目地址&#xff1a;https://github.com/jeecgboot/JeecgBoot…

【文科类cpci/cnki会议,主题广泛】第九届现代管理、教育与社会科学国际学术会议(MMET2024)

会议信息 点击跳转会议官网&#xff08;更多会议信息可添加会议官网下方负责老师-杨老师&#xff09; 大会时间&#xff1a;2024年09月20-22日 大会地点&#xff1a;中国-厦门 提交检索&#xff1a;CPCI&#xff0c;CNKI (知网检索快速稳定) 点击一键投稿 点击一键参会&a…