今天我们再来聊一下龙井预热:
作为全球最主要的Java用户之一,阿里内部在OpenJdk的基础上进行了扩展形成Ajdk,拥有更多的功能,而龙井(DragonWell)是Ajdk定制版的开源版本,供各界使用学习。这次用到的正是Ajdk的Jwarmup功能。
JwarmUp的基本原理:根据前一次程序运行的情况,记录热点代码以及类加载顺序等信息。在应用下一次启动的时候积极主动地对相关类进行加载,并积极编译相关代码,进而使得应用尽快使用上C2编译优化的指令。从而在流量进来之前,提前完成类的加载、初始化和方法编译, 跳过解释阶段, 直接执行编译好的native code, 避免一面解释执行一面后台编译带来的CPU与load飙高, rt超时等问题。
使用步骤:
• 记录编译信息阶段
-XX:+CompilationWarmUpRecording
-XX:CompilationWarmUpLogfile=jwarmup.log
-XX:CompilationWarmUpRecordTime=300
记录模式、记录存储的jwarmup.log,在5分钟后生成profiling data
• 使用编译信息阶段
-XX:+CompilationWarmUp
-XX:CompilationWarmUpLogfile=jwarmup.log
-XX:CompilationWarmUpDeoptTime=0
JWarmUp会在指定时间退优化warmup编译的方法,设置CompilationWarmUpDeoptTime为0可以取消这个定时。
1、recording记录下来的日志,是怎么分发到其他线上机的?
答:在应用启动的脚本文件进行控制:
• 预热节点,会将记录下来的编译信息上传到远程服务器oss上,
• 发布节点,在启动时从远处机器主动pull下来预热节点上传的编译信息。
2、是怎么制定一台机器做recording的呢?是访问某个url还是判断beta机器?
答:是通过访问oss做了一个类似于“文件锁”的东西,先拿到锁的beta机器做为预热节点,其余机器为发布节点。想要达到预热的效果请确保:
• 发布的机器的参数中有 -XX:+CompilationWarmUp
• 每次beta发布后,记得检查下编译信息文件是否已经上传
• beta发布的那台机器必须是有流量的,Recording时间不要太短,尽量多编译一些方法。
如果不保证上述两点的话,便无法完成预热发布,即没有充分利用beta的编译信息,仍然走正常发布的流程
分析:
jwarmup使用的场景如下图蓝色曲线所示:项目发布阶段,大量的解释执行时把CPU占满,导致没有足够的CPU进行编译,会导致CPU打满并长时间在解释运行,没有机会编译,CPU的利用率会长时间居高不下。而开启了jwarmup后如下图红色曲线所示,大大缩短了编译的时间。
对于我们消息应用发布cpu利用率抖动(CPU利用率在短时间内飙高)的问题,jwarmup并不能避免。即jwarmup能跳过解释执行阶段直接进入JIT编译,而我们的应用CPU 飙高正是因为JIT过于激进。但是这种思路仍值得我们学习和借鉴。