如何衡量方法分配率?
how to measure method allocation rate?
是否有针对 JVM
的分析器或工具(jconsole
、jfr
、VisualVM
、...)显示其分配率的方法?
我的意思是,像这样
org.package1.Class1.method1, 145k
org.package2.Class3.method5, 34k
此外,我正在寻找一种方法来查看哪些方法因分配暂停而被中断最多。
VisualVM
,例如,按线程显示分配率,而不是按方法
JFR
允许跟踪垃圾收集事件并进行某种内存和方法分析。但后来,使用 JMC 我无法按方法查看分配率。方法分析用于 cpu 火焰图。
也许不可能,或者没有意义。但这只是为了 gc 学习目的,我想进一步调查。
JDK 飞行记录器 (JFR) 可以测量每个分配站点(方法)的分配率,但它是基于样本的,因此它以准确性换取开销。你需要几千个样本。为每个分配记录堆栈跟踪(或方法)的开销是巨大的,并且会使应用程序停止。
JDK16引入了一个新的事件(ObjectAllocationSample),它限制了每秒的事件数。您应该能够在 JMC 中看到它。如果没有,这里有一个小程序,可以为您提供每个方法的分配直方图。
import java.io.IOException;
import java.nio.file.Path;
import java.util.*;
import jdk.jfr.consumer.*;
public class AllocationHistogram {
public static void main(String[] args) throws IOException {
if (args.length != 1) {
System.err.println("Must specify a recording file.");
return;
}
Map<String, Long> histogram = new HashMap<>();
try (var es = EventStream.openFile(Path.of(args[0]))) {
es.onEvent("jdk.ObjectAllocationSample", e -> {
RecordedStackTrace s = e.getStackTrace();
if (s != null) {
RecordedFrame topFrame = s.getFrames().get(0);
if (topFrame.isJavaFrame()) {
RecordedMethod m = topFrame.getMethod();
String className = m.getType().getName();
String key = className + "." + m.getName();
histogram.merge(key, e.getLong("weight"), (a, b) -> a + b);
}
}
});
es.start();
}
var list = new ArrayList<>(histogram.entrySet());
list.sort(Map.Entry.<String, Long>comparingByValue().reversed());
for (var entry : list) {
System.out.printf("%12dk %s\n", entry.getValue() /1024, entry.getKey());
}
}
}
用法:
$ java -XX:StartFlightRecording:filename=recording.jfr ...
$ # Stop the program after two minutes (CTRL+C)
$ java AllocationHistogram.java recording.jfr
16688k java.util.HashMap.newNode
1022k java.lang.AbstractStringBuilder.<init>
511k java.lang.Long.valueOf
... ...
是否有针对 JVM
的分析器或工具(jconsole
、jfr
、VisualVM
、...)显示其分配率的方法?
我的意思是,像这样
org.package1.Class1.method1, 145k
org.package2.Class3.method5, 34k
此外,我正在寻找一种方法来查看哪些方法因分配暂停而被中断最多。
VisualVM
,例如,按线程显示分配率,而不是按方法JFR
允许跟踪垃圾收集事件并进行某种内存和方法分析。但后来,使用 JMC 我无法按方法查看分配率。方法分析用于 cpu 火焰图。
也许不可能,或者没有意义。但这只是为了 gc 学习目的,我想进一步调查。
JDK 飞行记录器 (JFR) 可以测量每个分配站点(方法)的分配率,但它是基于样本的,因此它以准确性换取开销。你需要几千个样本。为每个分配记录堆栈跟踪(或方法)的开销是巨大的,并且会使应用程序停止。
JDK16引入了一个新的事件(ObjectAllocationSample),它限制了每秒的事件数。您应该能够在 JMC 中看到它。如果没有,这里有一个小程序,可以为您提供每个方法的分配直方图。
import java.io.IOException;
import java.nio.file.Path;
import java.util.*;
import jdk.jfr.consumer.*;
public class AllocationHistogram {
public static void main(String[] args) throws IOException {
if (args.length != 1) {
System.err.println("Must specify a recording file.");
return;
}
Map<String, Long> histogram = new HashMap<>();
try (var es = EventStream.openFile(Path.of(args[0]))) {
es.onEvent("jdk.ObjectAllocationSample", e -> {
RecordedStackTrace s = e.getStackTrace();
if (s != null) {
RecordedFrame topFrame = s.getFrames().get(0);
if (topFrame.isJavaFrame()) {
RecordedMethod m = topFrame.getMethod();
String className = m.getType().getName();
String key = className + "." + m.getName();
histogram.merge(key, e.getLong("weight"), (a, b) -> a + b);
}
}
});
es.start();
}
var list = new ArrayList<>(histogram.entrySet());
list.sort(Map.Entry.<String, Long>comparingByValue().reversed());
for (var entry : list) {
System.out.printf("%12dk %s\n", entry.getValue() /1024, entry.getKey());
}
}
}
用法:
$ java -XX:StartFlightRecording:filename=recording.jfr ...
$ # Stop the program after two minutes (CTRL+C)
$ java AllocationHistogram.java recording.jfr
16688k java.util.HashMap.newNode
1022k java.lang.AbstractStringBuilder.<init>
511k java.lang.Long.valueOf
... ...