1+ package com .jsoniter .demo ;
2+
3+ import java .io .File ;
4+ import java .lang .management .ManagementFactory ;
5+ import java .util .Arrays ;
6+ import java .util .Collection ;
7+ import java .util .Collections ;
8+ import java .util .List ;
9+ import org .openjdk .jmh .infra .BenchmarkParams ;
10+ import org .openjdk .jmh .profile .ExternalProfiler ;
11+ import org .openjdk .jmh .results .AggregationPolicy ;
12+ import org .openjdk .jmh .results .Aggregator ;
13+ import org .openjdk .jmh .results .BenchmarkResult ;
14+ import org .openjdk .jmh .results .Result ;
15+ import org .openjdk .jmh .results .ResultRole ;
16+
17+ /**
18+ *
19+ * @author zoly
20+ */
21+ public final class JmhFlightRecorderProfiler implements ExternalProfiler {
22+
23+ private static final String DUMP_FOLDER = System .getProperty ("jmh.stack.profiles" , "/tmp" );
24+
25+ private static final String DEFAULT_OPTIONS = System .getProperty ("jmh.fr.options" ,
26+ "defaultrecording=true,settings=profile" );
27+
28+
29+
30+ @ Override
31+ public Collection <String > addJVMInvokeOptions (final BenchmarkParams params ) {
32+ return Collections .emptyList ();
33+ }
34+
35+ private volatile String dumpFile ;
36+
37+ private static volatile String benchmarkName ;
38+
39+ public static String benchmarkName () {
40+ return benchmarkName ;
41+ }
42+
43+
44+ /**
45+ * See:
46+ * http://docs.oracle.com/cd/E15289_01/doc.40/e15070/usingjfr.htm
47+ * and
48+ * http://docs.oracle.com/cd/E15289_01/doc.40/e15070/config_rec_data.htm
49+ * @param params
50+ * @return
51+ */
52+ @ Override
53+ public Collection <String > addJVMOptions (final BenchmarkParams params ) {
54+ final String id = params .id ();
55+ benchmarkName = id ;
56+ dumpFile = DUMP_FOLDER + '/' + id + ".jfr" ;
57+ String flightRecorderOptions = DEFAULT_OPTIONS + ",dumponexit=true,dumponexitpath=" + dumpFile ;
58+ return Arrays .asList (
59+ "-XX:+FlightRecorder" ,
60+ "-XX:FlightRecorderOptions=" + flightRecorderOptions );
61+ }
62+
63+ @ Override
64+ public void beforeTrial (final BenchmarkParams benchmarkParams ) {
65+ final List <String > inputArguments = ManagementFactory .getRuntimeMXBean ().getInputArguments ();
66+ // if (new Version(org.spf4j.base.Runtime.JAVA_VERSION).compareTo(new Version("1.8.0_40")) <= 0
67+ // && !inputArguments.contains("-XX:+UnlockCommercialFeatures")) {
68+ // throw new RuntimeException("-XX:+UnlockCommercialFeatures must pre present in the JVM options,"
69+ // + " current options are: " + inputArguments);
70+ // }
71+ }
72+
73+
74+ @ Override
75+ public boolean allowPrintOut () {
76+ return true ;
77+ }
78+
79+ @ Override
80+ public boolean allowPrintErr () {
81+ return false ;
82+ }
83+
84+
85+ @ Override
86+ public String getDescription () {
87+ return "Java Flight Recording profiler runs for every benchmark." ;
88+ }
89+
90+ @ Override
91+ public Collection <? extends Result > afterTrial (final BenchmarkResult bp , final long l ,
92+ final File file , final File file1 ) {
93+ NoResult r = new NoResult ("Profile saved to " + dumpFile + ", results: " + bp
94+ + ", stdOutFile = " + file + ", stdErrFile = " + file1 );
95+ return Collections .singleton (r );
96+ }
97+
98+ private static final class NoResult extends Result <NoResult > {
99+ private static final long serialVersionUID = 1L ;
100+
101+ private final String output ;
102+
103+ NoResult (final String output ) {
104+ super (ResultRole .SECONDARY , "JFR" , of (Double .NaN ), "N/A" , AggregationPolicy .SUM );
105+ this .output = output ;
106+ }
107+
108+ @ Override
109+ protected Aggregator <NoResult > getThreadAggregator () {
110+ return new NoResultAggregator ();
111+ }
112+
113+ @ Override
114+ protected Aggregator <NoResult > getIterationAggregator () {
115+ return new NoResultAggregator ();
116+ }
117+
118+ private static class NoResultAggregator implements Aggregator <NoResult > {
119+
120+ @ Override
121+ public NoResult aggregate (final Collection <NoResult > results ) {
122+ StringBuilder agg = new StringBuilder ();
123+ for (NoResult r : results ) {
124+ agg .append (r .output );
125+ }
126+ return new NoResult (agg .toString ());
127+ }
128+ }
129+ }
130+
131+ @ Override
132+ public String toString () {
133+ return "JmhFlightRecorderProfiler{" + "dumpFile=" + dumpFile + '}' ;
134+ }
135+
136+ }
0 commit comments