An Introduction to JWarmup

简介: 一、JWarmup背景 二、JWarmup功能 三、案例演示

一、JWarmup背景 

(一)应用程序预热 

Java的方法要被执行,首先这个方法所在的类需要被JVM加载,这个过程包括各类文件的验证、解析、链接以及类的初始化。当这个类被加载进来了以后,JVM就可以去执行这个方法。 

JVM在刚开始的时候会使用模板解释器去解释执行方法,模板解释器除了一个个去执行方法中的Bytecodes之外,还会额外收集关于方法执行动态运行的信息,例如方法执行的调用次数,调用时一些类型的信息等。这些信息都会提供给JVM的即时编译器,由它利用这些信息将刚才解释执行发现的热点方法编译成为Native Code。这样JVM就不用模板解释器去执行这些方法,而是去执行性能更高的Native Code,从而使应用程序的性能得到大幅提升。 

当大多数热点方法都被编译成为Native Code以后,应用程序的预热就完成了 

 

(二)遇到的问题 

Java有非常丰富的应用场景,一个典型的场景就是我们会用Java写一些 Web服务在Web服务的部署过程中,会发现预热给我们带来非常大的困扰。当我们把一个Web服务部署到线上后,应用启动完成,此时就会有大量的用户请求进入。 

这个时候由于有大量的热点方法需要被编译,JVM的编译线程会非常忙碌,因为它需要占用大量的CPU将这些方法编译成为Native Code。同时又因为用户的线程需要执行解决用户的请求,因此它也会占用大量的CPU,并且会抢占编译线程所使用的CPU,这样就会导致编译线程无法尽快把这些热点方法编译到Native Code,使得应用程序长时间运行在解释执行的状态,降低服务的质量同时服务的RT会增加,服务所使用的CPU也会非常的高,这就是在真实场景中所遇到应用程序预热的问题接下来我们来看一下阿里巴巴Dragonwell 8中的JWarmup特性是如何解决这个问题。 

 

 

二、JWarmup功能 

image.jpeg 

上方为JWarmup流程图,它将应用程序的发布分成了两个阶段,分别是Recording和Replaying。在Recording阶段,JVM会接受线上的请求,同时记录JVM即时编译器它所编译方法的信息,并且将这些信息都输出到一个文件之中。 

等到第二次再去启动的时候,JVM就可以去读取刚刚所记录的这些方法编译的信息,同时会主动的触发即时编译器编译刚刚记录的热点方法,使得在用户请求到来之前,就把热点方法编译成为性能较高的Native Code,避免了用户请求大量进入的时候做编译,这样就能够进一步提高应用程序的性能,节约CPU使用率。 

 

 

三、案例演示 

(一)Demo代码 

image.png 

下面根据一个简单的例子展示如何使用JWarmup功能 

上方为一个简单的 Java程序,在这个程序之中有一个循环用来模拟线上应用的一个热点,循环会反复调用一个方法。 

 

(二)Recording 

如何去使用JWarmup的记录功能Recording 

-XX:+CompilationWarmUpRecording 

-XX: CompilationWarmUpRecording=30 

-XX: CompilationWarmUpLogfile=./jwarmup.log 

-XX:-ClassUnloading 

第一个参数表示去打开JWarmup的记录功能 

第二个参数表示需要记录的时间,在当前Demo之中选择记录30秒 

第三个参数表示记录编译信息生成文件的路径在这个Demo中,我们将这个文件生成在当前目录下的jwarmup.log这个文件 

第四个参数由于JWarmup的Recording功能不支持ClassUnloading,所以需要将这一功能关闭。 

设定的记录时间到了以后,JWarmup会将记录好的编译信息输出到指定的文件之中,同时会在应用程序的输出中看到以下这样一条日志,表明记录是成功的。 

image.png 

 

(三)Replaying 

如何使用JWarmup的Replaying功能 

  • 添加JVM参数: 

-XX:+CompilationWarmUp 

-XX:+CompilationWarmUpLogfile=./jwarmup.log 

-XX:+PrintCompilationWarmUpDetail 

第一个参数表示使用JWarmup的编译功能 

第二个参数需要指定刚刚记录的包含编译信息的文件,在当前Demo之中,就是刚刚所记录的当前目录下的jwarmup.log文件 

第三个参数表示我希望JWarmup打印出一些详细的日志,帮助我记录JWarmup工具的一些行为 

当把这些参数配置好以后,将服务启动,等待一些关键的类的加载完成可以使用jcmd <pid> JWarmup -notify主动触发Warmup的编译。 

Warmup编译完成后,可以在程序的标准输出中看到下面三条log,就表示这一次Warmup编译是成功的 

image.png 

以上就是关于JWarmup的基本介绍,包含JWarmup所需要解决的问题,解决方法,以及用案例讲述如何使用JWarmup功能同时我们对JWarmup这个功能还做了非常多的改进,形成了我们另外一份工作:JWarmup2 

image.png 

上方为JWarmup2整体流程图,可以看到在这份工作之中,我们记录了更加丰富的信息,去更好解决应用程序预热的问题。 

首先我们会使用JFR(Java Flight Recorder)统一所记录的编译的信息,这些信息也可以形成一个JFR文件,使用JDK官方所提供的Java Mission Control浏览所记录的所有热点方法的信息 

此外我们除了记录一些方法的编译,还记录了每一个方法它所依赖的类的信息。这样子在我们第二步预热的时候,就可以根据这些依赖的信息,当我们看到一个方法,它所有的依赖的类都被加载了以后,就会自动触发这个方法的Warmup编译,避免了人工手动触发Warmup编译 

此外我们还额外记录了这些方法所有的Profiling信息,这些信息能够帮助我们在第二步去更好地生成Warmup的代码,从而进一步提高应用程序的性能 

JWarmup2未来将在阿里巴巴Dragonwell 11中开源,欢迎大家使用。 

相关文章
|
存储 缓存 算法
The art of multipropcessor programming 读书笔记-硬件基础1
The art of multipropcessor programming 读书笔记-硬件基础1
The art of multipropcessor programming 读书笔记-硬件基础1
|
存储 缓存 Java
The art of multipropcessor programming 读书笔记-硬件基础2
The art of multipropcessor programming 读书笔记-硬件基础2
The art of multipropcessor programming 读书笔记-硬件基础2
|
设计模式 缓存 算法
【Java并发编程实战14】构建自定义同步工具(Building-Custom-Synchronizers)(下)
JDK包含许多存在状态依赖的类,例如FutureTask、Semaphore和BlockingQueue,他们的一些操作都有前提条件,例如非空、任务已完成等。
170 0
|
存储 安全 C#
《Effective C#中文版:改善C#程序的50种方法》读书笔记
  从去年找工作以来,都没什么时间写博客[找工作的体会:建议以后有自己开公司的IT人一定要找IT专业人员做HR,好多公司的HR并不能真正发掘人才,他们形成了太多的偏见,如在学校期间学不了什么东西、只看学校有多少奖励等。
1346 0
|
缓存 Java API
Java并发编程实战系列14之构建自定义的同步工具 (Building Custom Synchronizers)
类库中包含了许多存在状态依赖的类,例如FutureTask、Semaphore和BlockingQueue,他们的一些操作都有前提条件,例如非空,或者任务已完成等。
1348 0