简体   繁体   English

JVM JIT 编译器优化的限制

[英]Limits of JVM JIT-Compiler Optimizations

I am currently working on a compiler from a custom DSL to Java while performing some rudementary performance optimizations in the process.我目前正在研究从自定义 DSL 到 Java 的编译器,同时在此过程中执行一些基本的性能优化。 My biggest problem is that there are no academic resources to be found about what JIT-Compilers will do in regards to optimization (passes) or to what extend they will do it (eg complex dead-code-elimination, see example below).我最大的问题是,没有找到关于 JIT 编译器将在优化(通过)方面做什么或在什么范围内进行(例如,复杂的死代码消除,参见下面的示例)的学术资源。 There are many blog posts saying JIT-Compilers won't do all the optimizations an AOT-Compiler would do because of certain time-constraints, but none mentions what this actually means.有很多博客文章说由于某些时间限制,JIT 编译器不会做 AOT 编译器会做的所有优化,但没有提到这实际上意味着什么。 Is there a general rule of thumb ?是否有一般的经验法则? Do I need to dive into eg the OpenJDK C++ source to understand this?我是否需要深入研究 OpenJDK C++ 源代码才能理解这一点? Is there any research about this?有没有这方面的研究? And if there isn't, is there are least a credible ressource about what kind of optimizations the JVM JIT does ?如果没有,是否有关于 JVM JIT 进行哪些优化的最可靠资源? The latest resources I have found are about Java 5, which is quite outdated ( http://www.oracle.com/technetwork/java/5-136747.html )我发现的最新资源是关于 Java 5 的,它已经过时了 ( http://www.oracle.com/technetwork/java/5-136747.html )

Here is a simplified example of a ,,complex dead-code elimination" scenario which I have found the JVM JIT not to be able to eliminate, given the Variable cells_S_S_S is not used anywhere (bear in mind this is auto-generated code):这是一个简单的例子,复杂的死代码消除”场景我发现JVM JIT无法消除,因为变量cells_S_S_S没有在任何地方使用(记住这是自动生成的代码):

List<List<List<Cell>>> cells_S_S_S = new ArrayList<>(pla_S.size());
...
for (int pla_S_itr_45 = 0; pla_S_itr_45 < pla_S_size_45; ++pla_S_itr_45) {
        ...
        List<List<Cell>> cells_S_S = new ArrayList<>(tmpVarIf20_S.size());
        for (int tmpVarIf20_S_itr_44 = 0; tmpVarIf20_S_itr_44 < tmpVarIf20_S_size_44; ++tmpVarIf20_S_itr_44) {
            ...
            List<Cell> cells_S = _state.getCells();
            ...
            cells_S_S.add(cells_S);
        }
        ...
        cells_S_S_S.add(cells_S_S);
    }

This sort of ,,nested dead-code" was not eliminated which had me perform said optimizations on my own.这种“嵌套死代码”并没有被消除,这让我自己执行了所说的优化。

In short: I want to know what the JVM JIT is capable of so that I can focus my own optimization passes on the right areas.简而言之:我想知道 JVM JIT 的功能,以便我可以将自己的优化过程集中在正确的领域。

I want to know what the JVM JIT is capable of so that I can focus my own optimization passes on the right areas.我想知道 JVM JIT 的功能,以便我可以将自己的优化过程集中在正确的领域。

Simple answer: Don't.简单的回答:不要。

You have to consider two things:你必须考虑两件事:

  1. Yes, the Oracle HotSpot JVM JIT engine performs a wide range of optimisations during multiple passes.是的,Oracle HotSpot JVM JIT 引擎在多次通过期间执行广泛的优化。 Some of those you listed (dead-code elimination, inlining, de-virtualization, etc...) and many more.您列出的一些(死代码消除、内联、去虚拟化等)等等。
    It's important to note that the behaviour of the JIT Engine is not standardized and JVMs from other company behave in different ways.需要注意的是,JIT 引擎的行为不是标准化的,其他公司的 JVM 的行为方式也不同。 I've never seen a document describing comprehensively how HotSpot takes its decisions internally or the list of optimizations supported and I highly doubt such document exists (not from Oracle, not from the community).我从未见过全面描述 HotSpot 如何在内部做出决策或支持的优化列表的文档,我非常怀疑此类文档是否存在(不是来自 Oracle,也不是来自社区)。 You could dive into the source of the HotSpot VM, but:您可以深入了解 HotSpot VM 的来源,但是:
  2. HotSpot continuously tries to determine hot spots in your application and in a non-deterministic way decide what needs to be jitted, how to do it in the current context(for hotter methods it makes sense to apply costly optimizations) and which jitted methods need to be discarded and possibly recompiled. HotSpot 不断尝试确定应用程序中的热点,并以不确定的方式决定需要 jitted 的内容、在当前上下文中如何执行(对于较热的方法,应用代价高昂的优化是有意义的)以及哪些 jitted 方法需要被丢弃并可能重新编译。
    The state of your application is not stable, and the JIT engine constantly decide what to do with it and choses which set of optimizations will be applied depending on the current environment.您的应用程序的状态不稳定,JIT 引擎不断决定如何处理它,并根据当前环境选择将应用哪组优化。

You are trying to optimize the code that you are transpiling from your DSL for a specific JIT behaviour, but every assumption you are making could be valid for one specific run but not for another.您正在尝试针对特定的 JIT 行为优化从 DSL 转译的代码,但是您所做的每个假设可能对一次特定的运行有效,但对另一次无效。 Or not being valid anymore after a while, when the jit engine decides to drop the jitted version of your method to free memory or to compile it again with different results.或者一段时间后不再有效,当 jit 引擎决定放弃你的方法的 jitted 版本以释放内存或以不同的结果再次编译它时。

The only difference between JIT and AOT is that for the latter there are no time constraints, so you try to produce the best code you can, for some measure of quality. JIT 和 AOT 之间的唯一区别是后者没有时间限制,因此您可以尝试生成最好的代码,以达到某种程度的质量。

JIT Optimization is actually far more powerful than Whole-Program optimization. JIT 优化实际上比Whole-Program 优化强大得多。 JIT Optimization adapts the code temporarily for the best performance and makes extremely unsafe optimizations based on assumptions about the code. JIT 优化临时调整代码以获得最佳性能,并基于对代码的假设进行极其不安全的优化。 For example, the JIT optimizer can precompute something and then rolls it back if the assumption turns wrong.例如,JIT 优化器可以预先计算某些内容,然后在假设出错时将其回滚。 The JIT inliner helps the JIT optimizer by inlining methods so they can be adapted to their specific caller. JIT 内联器通过内联方法帮助 JIT 优化器,以便它们可以适应特定的调用者。

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

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