JIT 会做乐观的假设:这个调用点只有一种类型、这个分支不会走到。假设被打破时 JVM 退回解释器重新来过,这就是 deoptimization。这篇用真实的基准和 deopt 日志看三种典型情况:类型污染、冷分支变热、数组越界。
只见过 Sq 一种实现:0.69 ns/次调用(热身后 5 次的中位 0.69)
--- 现在让调用点见到第 2 种实现 Rect ---
两种实现(Sq/Rect 交替)连续 8 次的 ns/次:[2.55, 0.68, 0.83, 0.84, 0.83, 0.81, 0.85, 0.65]
--- 第 3 种实现 Tri ---
三种实现连续 8 次的 ns/次:[3.82, 3.55, 3.57, 3.55, 3.57, 3.56, 3.57, 3.27]
四种实现连续 8 次的 ns/次:[3.20, 3.19, 3.17, 3.18, 3.16, 3.16, 3.19, 3.16]
再回到只有 Sq 一种实现:[2.31, 2.28, 2.29, 2.28, 2.29](调用点的类型 profile 里已经有 4 种,不会退回去)
-Xlog:deoptimization=debug 共 19 行,其中涉及 Main 的 11 行;节选:
cid= 22 level=4 Main.callAll([LMain$Shape;I)J trap_bci=28 class_check maybe_recompile pc=… relative_pc=…
cid= 21 osr level=4 Main.callAll([LMain$Shape;I)J trap_bci=28 osr_bci=14 class_check maybe_recompile pc=… relative_pc=…
cid= 151 level=4 Main.callAll([LMain$Shape;I)J trap_bci=28 bimorphic_or_optimized_type_check maybe_recompile pc=… relative_pc=…
cid= 149 osr level=4 Main.callAll([LMain$Shape;I)J trap_bci=28 osr_bci=14 bimorphic_or_optimized_type_check maybe_recompile pc=… relative_pc=… 从未走过 rare 分支:[0.31, 0.31, 0.31, 0.32, 0.30] ns/次
--- 现在 rare 分支开始每 1000 次出现一次 ---
rare 分支每 1000 次出现一次:[2.28, 0.90, 0.92, 0.92, 0.91, 0.91] ns/次
又回到从不走 rare 分支:[0.33, 0.31, 0.30, 0.31, 0.31] ns/次
-Xlog:deoptimization=debug 共 9 行,其中涉及 Main 的 6 行;节选:
cid= 15 level=4 Main.runBranch(II)J trap_bci=8 predicate maybe_recompile pc=… relative_pc=…
cid= 11 level=4 Main.branchy(IZ)I trap_bci=1 unstable_if reinterpret pc=… relative_pc=…
cid= 14 osr level=4 Main.runBranch(II)J trap_bci=5 osr_bci=5 profile_predicate maybe_recompile pc=… relative_pc=… 下标始终在范围内:[0.60, 0.60, 0.61, 0.60] ns/次
--- 现在每次迭代都越界并被 catch ---
每次迭代越界一次:[329.95, 47.10, 0.91, 0.90] ns/次(包含创建异常对象和栈跟踪的开销)
-Xlog:deoptimization=debug 共 6 行,其中涉及 Main 的 3 行;节选:
cid= 15 level=4 Main.runIdx([III)J trap_bci=16 unstable_if reinterpret pc=… relative_pc=…
cid= 11 level=4 Main.idx([II)I trap_bci=2 range_check make_not_entrant pc=… relative_pc=…
cid= 14 osr level=4 Main.runIdx([III)J trap_bci=16 osr_bci=5 unstable_if reinterpret pc=… relative_pc=…