简体   繁体   English

JVM编译时间与代码缓存

[英]JVM Compile Time vs Code Cache

I've been benchmarking my app and analyzing it with JMC. 我一直在对我的应用程序进行基准测试并使用JMC进行分析。 I've noticed that under load, it performs quite a bit of JIT compiling. 我注意到在负载下,它执行了相当多的JIT编译。 If I send a large amount of transactions per second, the compile time spikes. 如果我每秒发送大量事务,则编译时间会激增。 The compile time always grows proportionally with any heavy load test against the app. 编译时间总是与针对应用程序的任何重负载测试成比例增长。

I've also observed that the Code Cache slowly rises as well. 我还观察到代码缓存也慢慢上升。 So I decided to raise the Code Cache reserve to 500MB to test. 所以我决定将代码缓存保留提高到500MB进行测试。 Bad move! 不好动! Now it's spending even more time performing JIT. 现在它花费更多时间执行JIT。

Then I explicitly disabled code cache flushing via -XX:-UseCodeCacheFlushing . 然后我通过-XX:-UseCodeCacheFlushing显式禁用了代码缓存刷新。 However, I noticed that the peak Code Cache usage is larger than the current size. 但是,我注意到代码缓存的峰值使用率大于当前大小。 This leads me to a couple of questions: 这引出了几个问题:

在此输入图像描述

  1. Does the JVM try to cache every JIT compilation? JVM是否尝试缓存每个JIT编译?
  2. Why is the peak Code Cache size bigger than the current size even though I disabled flushing? 为什么即使禁用了刷新,峰值代码缓存大小也会大于当前大小?
  3. Is there "temporary" compiled code that's automatically removed after the function ends? 是否有“临时”编译代码在函数结束后自动删除?

In HotSpot JVM all JIT-compiled methods stays in CodeCache until they are reclaimed. 在HotSpot JVM中,所有JIT编译的方法都保留在CodeCache中,直到它们被回收为止。 UseCodeCacheFlushing affects reclamation of cold (but still valid) compiled methods. UseCodeCacheFlushing影响冷(但仍然有效)编译方法的回收。 However, CodeCache may also contain obsolete or invalidated methods ("zombies") which are subject to purge at the next sweep cycle even with -XX:-UseCodeCacheFlushing . 但是,CodeCache还可能包含过时或无效的方法(“僵尸”),即使使用-XX:-UseCodeCacheFlushing ,这些方法也会在下一个扫描周期进行清除。

  • In a tiered compilation mode (default since JDK 8) a method may be compiled multiple times with a different level of optimizations. 分层编译模式中(默认自JDK 8),可以使用不同级别的优化来编译多次方法。 Once an optimized (tier 4) version of a method is installed, the previous version becomes obsolete and can be reclaimed after all activations of that version complete. 一旦安装了方法的优化(第4层)版本,之前的版本就会过时,并且可以在完成该版本的所有激活后回收。
  • A speculatively compiled method may become invalid when the speculation fails (eg after a new class is loaded). 当推测失败时(例如,在加载新类之后),推测编译的方法可能变得无效。 Such method also becomes zombie and can be later reclaimed. 这种方法也变成僵尸,以后可以回收。
  • Another example is an OSR compilation . 另一个例子是OSR编译 This is a version of a method that was compiled specially for transferring execution from interpreter to compiled code while the method is running. 这是一个专门编译的方法版本,用于在方法运行时将执行从解释器转移到编译代码。 Answering your 3rd question, this is a kind of "temporary" method which becomes obsolete after the full version of compiled method is installed and all OSR activations complete. 回答第3个问题,这是一种“临时”方法,在安装完整版本的编译方法并完成所有OSR激活后,该方法就会过时。

There is a separate JVM flag -XX:-MethodFlushing to prevent sweeping CodeCache altogether, including zombie methods. 有一个单独的JVM标志-XX:-MethodFlushing来防止彻底扫描CodeCache,包括僵尸方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM