分层编译
分层编译
随着代码的执行,-Xcomp
除了纯编译和默认的
// globalDefinitions.hpp
enum CompLevel {
CompLevel_any = -1,
CompLevel_all = -1,
CompLevel_none = 0, // Interpreter
CompLevel_simple = 1, // C1
CompLevel_limited_profile = 2, // C1, invocation & backedge counters
CompLevel_full_profile = 3, // C1, invocation & backedge counters + mdo
CompLevel_full_optimization = 4, // C2 or Shark
... ...
};
目前分层编译包括五个编译层次:Level 0 - Level 4。大家可以在启动参数中加入
Level0 即解释执行,由解释器负责执行java 方法。这种方式无编译开销,但速度很慢;解释器并不开启性能监控功能,可触发第一层编译。Level1 程序由C1 编译器编译为本地机器指令执行,C1 编译器会对字节码进行简单和可靠的优化,以达到更快的编译速度。编译方法受限,编译开销比较低,性能比Level4 差,但强于其他层次。Level2 程序由C1 编译器编译为本地机器指令执行,但C2 编译器会启动一些编译耗时更长的优化(代码将有可能被重复编译多次) ,甚至有可能根据性能监控信息进行一些不可靠的激进优化。编译开销比较低,性能差于Level4 和Level1 。Level3 由C1 负责编译,除了方法执行次数和回边次数的统计外,还加入了对方法内部执行信息的统计,如一个分枝是否执行跳转,一个虚函数调用最终调用到哪个方法等信息。Level3 性能较差,仅比Level0 快,但是Level3 是Level4 编译的必要步骤。程序由C1 编译器编译为本地机器指令执行,采集性能数据进行优化措施;Level4 由C2 负责编译,它利用level3 收集的信息,对方法进行完全的优化,性能最好,但是编译开销也最大。程序由C2 编译器编译为本地机器指令执行,进行完全优化。
下述列举了判断一个方法是否需要触发编译的及编译到哪个层次的具体公式
参数 | 说明 | 默认值 |
---|---|---|
Tier3InvocationThreshold | 一个方法被调用多少次之后会进行 |
200 |
Tier4InvocationThreshold | 一个方法被调用多少次之后会进行 |
5000 |
Tier3CompileThreshold | 考虑回边的情况下,一个方法执行多少次之后会进行 |
2000 |
Tier4CompileThreshold | 考虑回边的情况下,一个方法执行多少次之后会进行 |
15000 |
Tier3BackEdgeThreshold | 一个方法中回边执行多少次会进行 |
60000 |
Tier4BackEdgeThreshold | 一个方法中回边执行多少次会进行 |
40000 |
CICompilerCount | 编译线程数目 | 无 |
Tier3LoadFeedback | 用来动态调整 |
5 |
Tier4LoadFeedback | 用来动态调整 |
3 |
Tier3DelayOn | 平均每个 |
5 |
Tier3DelayOff | 平均每个 |
2 |
最常见的
- 这个方法只是用来获取类中的某个域的值的
- 这个方法只是用来获取常量的
- 这个方法很小
满足这三个条件其中之一的方法会直接被编译成