关于jit:JAVA中的JIT-的工作原理

明天小编要给大家分享的是只是其中的一个小小的知识点——java中的JIT的工作原理。 工作原理当JIT编译启用时(默认是启用的),JVM读入.class文件解释后,将其发给JIT编译器。JIT编译器将字节码编译老本机机器代码。 通常javac将程序源代码编译,转换成java字节码,JVM通过解释字节码将其翻译成对应的机器指令,逐条读入,逐条解释翻译。很显然,通过解释执行,其执行速度必然会比可执行的二进制字节码程序慢。为了进步执行速度,引入了JIT技术。 在运行时JIT会把翻译过的机器码保存起来,已备下次应用,因而从实践上来说,采纳该JIT技术能够,能够靠近以前纯编译技术。 相干常识JIT是just in time,即时编译技术。应用该技术,可能减速java程序的执行速度。 JIT并不总是见效,不能冀望JIT肯定可能减速你代码执行的速度,更蹩脚的是她有可能升高代码的执行速度。这取决于你的代码构造,当然很多状况下咱们还是可能如愿以偿的。 从下面咱们晓得了之所以要敞开JIT java.lang.Compiler.disable(); 是因为放慢执行的速度。因为JIT对每条字节码都进行编译,造成了编译过程负担过重。为了防止这种状况,以后的JIT只对常常执行的字节码进行编译,如循环等。

April 7, 2023 · 1 min · jiezi

关于jit:服务启动过程性能波动的分析与解决方案

1. 前言本文仅分享本人在工作中遇到的问题时的解决方案和思路,以及排查的过程。重点还是分享排查的思路,知识点其实曾经挺老了。如有疑难或形容不妥,欢送赐教。2. 问题表象在工程启动的时候,零碎的申请会有一波超时,从监控来看,JVM 的GC(G1) 稳定较大,CPU稳定较大,各个业务应用的线程池稳定较大,内部IO耗时减少。零碎调用产生较多异样(也是因为超时导致)公布过程中的异样次数: 3. 先说论断因为JIT的优化,导致系统启动时触发了热点代码的编译,且为C2编译,引发了CPU占用较高,进而引发一系列问题,最终导致局部申请超时。4. 排查过程其实知识点就放在那里,重要的是可能将理论遇到的问题和知识点分割到一起并能更粗浅的了解这部分常识。这样能力转化为教训。4.1 最后的排查咱们的工程是一个算法排序工程,外面或多或少也加了一些小的模型和大大小小的缓存,而且从监控上来看,JVM 的GC 突刺和 CPU 突刺工夫极为靠近(这也是一个监控平台工夫不够精准的起因)。所以在后期,我消耗了大量精力和工夫去排查JVM,GC 的问题。首先举荐给大家一个网站:https://gceasy.io/ ,真的剖析GC日志巨好用。配合以下的JVM参数打印GC日志:-XX:+PrintGC 输入GC日志-XX:+PrintGCDetails 输入GC的具体日志-XX:+PrintGCTimeStamps 输入GC的工夫戳(以基准工夫的模式,你启动的时候相当于12点,跟实在工夫无关)-XX:+PrintGCDateStamps 输入GC的工夫戳(以日期的模式,如 2013-05-04T21:53:59.234+0800)-Xloggc:../logs/gc.log 日志文件的输入门路因为看到YGC重大,所以先后尝试了如下的办法: 调整JVM 的堆大小。即 -Xms, -Xmx 参数。有效。调整回收线程数目。即 -XX:ConcGCThreads 参数。有效。调整冀望单次回收工夫。即 -XX:MaxGCPauseMillis 参数,有效,甚至更惨。以上调整混合测试,均有效。鸡贼的办法。在加载模型之后sleep 一段时间,让GC安稳,而后再放申请进来,这样操作之后GC的确有些恶化,然而刚开始的申请依然有超时。(当然了,因为问题基本不在GC上)4.2 换个思路依据监控上来看,线程池,内部IO,启动时都有显著的RT回升而后降落,而且趋势十分统一,这种个别都是系统性问题造成的,比方CPU,GC,网卡,云主机超售,机房提早等等。所以GC既然无奈根治,那么就从CPU方面动手看看。因为系统启动时JVM会产生大量GC,无奈辨别是因为系统启动还没预热好就来了流量,还是说无论系统启动了多久,流量一来就会出问题。而我之前排查GC的操作,即加上了sleep工夫,恰好帮我看到了这个问题,因为能显著的看出,GC稳定的工夫,和超时的工夫,工夫点上曾经差了很多了,那就是说,稳定与GC无关,无论GC曾经如许安稳,流量一来,还是要超时。4.3 剖析利器Arthas不得不说,Arthas 真的是一个很好用的剖析工具,节俭了很多简单的操作。Arthas 文档: https://arthas.aliyun.com/doc...其实要剖析的外围还是流量最开始到来的时候,咱们的CPU到底做了什么,于是咱们应用Arthas剖析流量到来时的CPU状况。其实这部分也能够应用top -Hp pid , jstack 等命令配合实现,不开展叙述。CPU状况:图中能够看出C2 CompilerThread 占据了十分多的CPU资源。 4.4 问题的外围那么这个C2 CompilerThread 到底是什么呢。《深刻了解JAVA虚拟机》其实有对这部分的叙述,这里我就大白话给大家解释一下。其实Java在最开始运行的时候,你能够了解为,就是傻乎乎的依照你写的代码执行上来,称之为"解释器",这样有一个益处,就是很快,Java搞成.class ,很快就能启动,跑起来了,然而问题也很显著啊,就是运行的慢,那么聪慧的JVM开发者们做了一件事件,他们如果发现你有一些代码频繁的执行,那么他们就会在运行期间帮你把这段代码编译成机器码,这样运行就会飞快,这就是即时编译(just-in-time compilation 也就是JIT)。然而这样也有一个问题,就是编译的那段时间,消耗CPU。而C2 CompilerThread,正是JIT中的一层优化(共计五层,C2 是第五层)。所以,罪魁祸首找到了。5. 尝试解决解释器和编译器的关系能够如下所示: 就像下面说的,解释器启动快,然而执行慢。而编译器又分为以下五个档次。第 0 层:程序解释执行,默认开启性能监控性能(Profiling),如果不开启,可触发第二层编译;第 1 层:可称为 C1 编译,将字节码编译为本地代码,进行简略、牢靠的优化,不开启 Profiling;第 2 层:也称为 C1 编译,开启 Profiling,仅执行带办法调用次数和循环回边执行次数 profiling 的 C1 编译;第 3 层:也称为 C1 编译,执行所有带 Profiling 的 C1 编译;第 4 层:可称为 C2 编译,也是将字节码编译为本地代码,然而会启用一些编译耗时较长的优化,甚至会依据性能监控信息进行一些不牢靠的激进优化。所以咱们能够尝试从C1,C2编译器的角度去解决问题。5.1 敞开分层编译减少参数 : -XX:-TieredCompilation -client (敞开分层编译,开启C1编译)成果稀烂。CPU使用率继续高水位(相比于调整前)。的确没了C2 thread 的问题,然而猜想因为代码编译的不够C2那么优良,所以代码继续性能低下。CPU截图: 5.2 减少C2 线程数减少参数 :-XX:CICompilerCount=8 复原参数:-XX:+TieredCompilation成果个别,依然有申请超时。然而会少一些。CPU截图:5.3 推论其实从下面的剖析能够看出,如果绕不过C2,那么必然会有一些抖动,如果绕过了C2,那么整体性能就会低很多,这是咱们不愿看见的,所以敞开C1,C2,间接以解释器模式运行我并没有尝试。6. 解决方案6.1最终计划既然这部分抖动绕不过来,那么咱们能够应用一些mock 流量来接受这部分抖动,也能够称之为预热,在工程启动的时候,应用提前录制好的流量来使零碎热点代码实现即时编译,而后再接管真正的流量,这样就能够做到实在流量不抖动的成果。在零碎失常运行的过程中采集局部流量,并序列化为文件存储下来,当系统启动的时候,将文件反序列化为申请对象,进行流量重放。进而触发JIT的C2 compile,使CPU的稳定在预热期间内实现,不影响失常的线上的流量。6.2先放后果预计每次公布缩小10000次异样申请(仅计算异样不包含超时)。缩小因搜寻导流带来的其余业务的营收损失。其余相干搜寻的引流操作均缩小每次公布10000次申请的损失。异样的缩小状况: ...

May 26, 2022 · 1 min · jiezi

关于jit:MegEngine-里面的即时编译竟如此神奇可显著加快代码执行速度

本文整顿自 2 月 25 号 MegEngine 首期 Meetup 的分享。作者:王彪 | 旷视框架部异构计算组工程师视频回放:《JIT in MegEngine》_MegEngine Meetup 第一期一、背景什么是天元旷视天元(MegEngine)是一个深度学习框架,它次要蕴含训练和推理两方面内容。训练侧个别应用 Python 搭建网络;而推理侧思考到产品性能的因素,个别应用 C++ 语言集成天元框架。无论在训练侧还是推理侧,天元都负担着将训练和推理的代码运行到各种计算后端上的工作。目前天元反对的计算后端有 CPU、GPU、ARM 和一些畛域专用的加速器,笼罩了云、端、芯等各个场景。 天元次要有三大特色: 1.训推一体,不论是训练任务还是推理工作都能够由天元一个框架来实现。 2.动静联合,天元同时反对动态图和动态图,并且动静之间的转换也十分不便。 3.多平台的高性能反对。 如图 1 所示,咱们能够看到天元提供了 Python 和 C++ 两种接口。在图示意上分为动态图和动态图。运算层组件包含主动求导器、图优化和图编译等。天元的运行时模块包含内存治理和计算调度,其中内存治理包含动态内存治理和动态内存治理,以及亚线性内存优化技术。计算内核层蕴含了天元反对的所有计算后端,咱们后续会开源出更多的计算后端。除此之外,天元还蕴含了一个高性能异构通信库,它个别会在多机多卡的场景下被用到。 动态图和动态图是绝对的,在动态图下是没有计算图的概念的。但在动态图下,天元会保护一张计算图。如图 2 所示为天元中的计算图示意,图中圆形示意算子(operator),三角形示意输出。在天元框架中,动态图和动态图之间的转换只须要一条简略的语句即可实现,如下方代码所示: if __name__ == '__main__’: gm = ad.GradManager().attach(model.parameters()) opt = optim.SGD(model.parameters(), lr=0.0125, momentum=0.9, weight_decay=1e-4) <em> # 通过 trace 转换为动态图</em> @trace(symbolic=True) def train(): with gm: logits = model(image) loss = F.loss.cross_entropy(logits, label) gm.backward(loss) opt.step() opt.clear_grad() return loss loss = train() loss.numpy()什么是 AOT 和 JITAOT(Ahead Of Time) 和 JIT(Just In Time) 都是编译中的概念。以传统的 C/C++ 语言为例,咱们写完代码之后,个别会通过编译器编译生成可执行文件,而后再执行该可执行文件取得执行后果。如果咱们将从源代码编译生成可执行文件的过程称为 build 阶段,将执行可执行文件叫做 runtime 阶段的话,JIT 是没有build 阶段的,它只有 runtime 阶段。JIT 个别被用在解释执行的语言如 Python 中,JIT 会在代码执行的过程中检测热点函数,随后对热点函数进行重编译,下次运行时遇到热点函数则间接执行编译后果即可。这样做能够显著放慢代码执行的速度。 ...

July 26, 2021 · 3 min · jiezi