问题描述
我非常了解如何捕获JIT的去优化事件。
今天,我阅读了安德烈·潘金(Andrei Pangin)When busy-spining java thread is bound to physical core,can context switch happen by the reason that new branch in code is reached?的精彩回答,然后再考虑一下。
我想用JNI + JVMTI捕获JIT的取消优化事件,例如“ unstable_if,class_check等”,然后将警报发送到我的监视系统或其他任何东西。
有可能吗? 对JVM性能有什么影响?
解决方法
不常见的陷阱和取消优化是HotSpot实现的详细信息。您不会在像JVM TI这样的标准接口中找到它们(该接口是为通用虚拟机而不仅仅是HotSpot设计的)。
正如我的previous answer中所建议的那样,诊断欠优化的一种可能方法是添加-XX:+UnlockDiagnosticVMOptions -XX:+LogCompilation
选项并在编译日志中寻找<uncommon_trap>
。
另一种方法是使用async-profiler跟踪去优化事件。
为此,请使用-e Deoptimization::uncommon_trap_inner
。
如果使用jfr
输出格式,这将向您显示Java代码中发生非优化的位置,以及时间戳。
自JDK 14起,Flight Recorder(JDK-8216041)也会原生报告取消优化事件。使用JMC中的事件浏览器,您可能会发现所有不常见的陷阱,包括方法名称,字节码索引,取消优化的原因等。
以上所有方法的开销都足够小。在生产中使用async-profiler通常没有问题;如果录制设置不是多余的,则JFR也可以。
但是,除非常特殊的情况外,在概要分析非优化中没有太多用处。只要JVM在运行时了解有关该应用程序的更多信息,这对于典型的Java应用程序多次重新编译方法是绝对正常的。听起来可能很奇怪,但是不常见的陷阱是推测优化的常见技术:)如上图所示,即使是HashMap.put
之类的基本方法也可能会导致去优化,这很好。
在JDK 14(基于OpenJDK)中,您可以使用Event Steaming API以编程方式访问取消优化事件。没有来自本机的API。
import jdk.jfr.consumer.RecordingStream;
RecordingStream s = new RecordingStream();
s.enable("jdk.Deoptimization").withStackTrace();
s.onEvent("jdk.Deoptimization",e -> {
System.out.println("Time: " + e.getEndTime());
System.out.println("Reason: " + e.getString("reason"));
System.out.println("Action: " + e.getString("action"));
System.out.println("Instruction: "+ e.getString("instruction"));
System.out.println("Line Number: " + e.getInt("lineNumber"));
System.out.println("Bytecode Index" + e.getInt("bci"));
RecordedMethod m = e.getValue("method");
RecordedStackTrace st = e.getStackTrace();
RecordedThread t = e.getThread();
...
});
s.start();