JVM 先解释执行,再用 C1 快速编译,最后用 C2 深度优化。这篇用 PrintCompilation 看一个方法的层级变化,量出热身曲线,并对比解释器、只用 C1、默认分层与只用 C2 的总耗时。
16 5 3 Main::hot (31 bytes) 16 6 3 Main::mid (12 bytes) 16 7 4 Main::hot (31 bytes) 17 5 3 Main::hot (31 bytes) made not entrant 17 8 4 Main::mid (12 bytes) 18 6 3 Main::mid (12 bytes) made not entrant 19 9 % 3 Main::runBatch @ 5 (30 bytes) 19 10 3 Main::runBatch (30 bytes) 19 11 % 4 Main::runBatch @ 5 (30 bytes) 25 11 % 4 Main::runBatch @ 5 (30 bytes) COMPILE SKIPPED: Too many clones required in clone_for_use_outside_loop in partial peeling (retry at different 25 9 % 3 Main::runBatch @ 5 (30 bytes) made not entrant 25 12 % 1 Main::runBatch @ 5 (30 bytes) (列:时间 ms、编译序号、标志、层级、方法、字节码大小;% 表示 OSR 编译,「made not entrant」表示旧版本被替换)
每批 2000 次 mid() 调用的平均耗时(ns/次):第 1 批 137;第 2–3 批 90;第 4–10 批 37;第 11–30 批 27;第 31–100 批 17;第 101–300 批 16.2 前 12 批的 ns/次:137 87 92 85 34 28 28 28 28 28 28 28
[-Xint(只用解释器)] 3 次运行的中位:前 10 万次调用 38.1 ms;中间 2800 万次 10742 ms(范围 10635–10766);最后 200 万次 767.7 ms,383.9 ns/次 [-XX:TieredStopAtLevel=1(只用 C1)] 3 次运行的中位:前 10 万次调用 3.2 ms;中间 2800 万次 573 ms(范围 572–579);最后 200 万次 41.2 ms,20.6 ns/次 [默认(分层:解释器 → C1 → C2)] 3 次运行的中位:前 10 万次调用 3.3 ms;中间 2800 万次 401 ms(范围 399–404);最后 200 万次 28.5 ms,14.3 ns/次 [-XX:-TieredCompilation(只用 C2)] 3 次运行的中位:前 10 万次调用 4.2 ms;中间 2800 万次 760 ms(范围 755–768);最后 200 万次 50.3 ms,25.1 ns/次
CICompilerCount = 4
TieredStopAtLevel = 4
Tier3InvocationThreshold = 200
Tier3BackEdgeThreshold = 60000
Tier4InvocationThreshold = 5000
Tier4BackEdgeThreshold = 40000
Tier3MinInvocationThreshold = 100
Tier3CompileThreshold = 2000
Tier4CompileThreshold = 15000
Tier0ProfilingStartPercentage = 200
这个小程序(约 0.4 秒)一共编译的方法数,按层级: {'0': 17, '1': 4, '3': 19, '4': 5} ;「made not entrant」4 次