我试图了解Java Flight Recorder如何对使用本机库的应用程序进行采样(在我的例子中通过JNA)。
让我们写一个测试用例,将大部分时间花在本土上:
public class Main {
interface MyLib extends Library {
long doStuff(long seed);
}
public static void main(String[] args) {
MyLib myLib = (MyLib) Native.loadLibrary("mylib", MyLib.class);
LongStream.range(0, 10)
.map(myLib::doStuff)
.forEach(System.out::println);
}
}
doStuff是一个缓慢的,cpu绑定的函数
int64_t doStuff(int64_t acc) {
for (int i = 0; i < 1<<30; i++) { acc += i; }
return acc;
}
doStuff需要大约2秒才能在我的机器上执行,主机在~30秒内完成。我使用以下JVM选项使用jdk1.8.0_60运行此测试用例:-XX:+UnlockCommercialFeatures -XX:+FlightRecorder -XX:FlightRecorderOptions=defaultrecording=true,dumponexit=true,dumponexitpath=jna.jfr
。
当我打开jna.jfr
时,我发现转储包含单个堆栈跟踪事件。据我所知,与大多数分析器不同,JFR在本机代码运行时不会生成堆栈跟踪事件。我完全理解JFR不会对本机代码进行概要分析,但我原本期望使用在java /本机代码边界截断的堆栈跟踪生成堆栈跟踪事件。
我的设置有问题还是预期的行为?我发现它确实容易出错。如果您不仔细验证样本计数,很容易相信热点是Java代码,而大部分时间都花在本机代码中。
也不可能知道最昂贵的原生呼叫在哪里,这就是你首先使用探查器的原因:)
答案 0 :(得分:1)
Flight Recorder采样器仅在Java中发出事件。如果采样器遇到本机代码,则可以查看最后一个Java帧,但这不是如何实现的。