package org.openjdk.jmh.profile;
import org.openjdk.jmh.infra.BenchmarkParams;
import org.openjdk.jmh.infra.IterationParams;
import org.openjdk.jmh.results.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
abstract class AbstractHotspotProfiler implements InternalProfiler {
private final Method getListMethod;
private final Object bean;
private Map<String, Long> prevs;
public AbstractHotspotProfiler(String beanName, String methodName) throws ProfilerException {
try {
Class<?> helper = Class.forName("sun.management.ManagementFactoryHelper");
bean = helper.getMethod("get" + beanName).invoke(null);
getListMethod = bean.getClass().getMethod(methodName);
getListMethod.setAccessible(true);
getListMethod.invoke(bean);
} catch (ClassNotFoundException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
throw new ProfilerException("Problem initializing profiler (" + e.getMessage() + "), are you running HotSpot VM?");
}
}
@Override
public Collection<? extends Result> afterIteration(BenchmarkParams benchmarkParams, IterationParams iterationParams, IterationResult result) {
HotspotInternalResult res = counters();
Collection<ScalarResult> results = new ArrayList<>();
for (Map.Entry<String, Long> e : res.getDiff().entrySet()) {
results.add(new ScalarResult(Defaults.PREFIX + e.getKey(), e.getValue(), "?", AggregationPolicy.AVG));
}
return results;
}
@Override
public void beforeIteration(BenchmarkParams benchmarkParams, IterationParams iterationParams) {
prevs = new HashMap<>();
for (HotspotCounter counter : getCounters()) {
prevs.put(counter.getName(), convert(counter.getValue()));
}
}
public static Long convert(Object o) {
try {
return Long.valueOf(String.valueOf(o));
} catch (IllegalArgumentException iae) {
return null;
}
}
protected HotspotInternalResult counters() {
Map<String, Long> difference = new TreeMap<>();
Map<String, Long> current = new TreeMap<>();
for (HotspotCounter counter : getCounters()) {
Long prev = prevs.get(counter.getName());
if (prev != null) {
long diff = convert(counter.getValue()) - prev;
difference.put(counter.getName(), diff);
current.put(counter.getName(), convert(counter.getValue()));
}
}
return new HotspotInternalResult(current, difference);
}
public List<HotspotCounter> getCounters() {
try {
List<HotspotCounter> counters = new ArrayList<>();
for (Object c : (List) getListMethod.invoke(bean)) {
try {
counters.add(new HotspotCounter(c));
} catch (UnsupportedOperationException e) {
}
}
return counters;
} catch (IllegalAccessException | InvocationTargetException e) {
throw new IllegalStateException("Should not be here", e);
}
}
static class HotspotInternalResult {
private final Map<String, Long> current;
private final Map<String, Long> diff;
public HotspotInternalResult(Map<String, Long> current, Map<String, Long> diff) {
this.current = current;
this.diff = diff;
}
public Map<String, Long> getCurrent() {
return current;
}
public Map<String, Long> getDiff() {
return diff;
}
@Override
public String toString() {
return "difference: " + diff.toString();
}
}
private static class HotspotCounter {
private static final Method GET_VALUE;
private static final Method GET_NAME;
static {
Method name = null;
Method value = null;
try {
Class<?> cntClass = Class.forName("sun.management.counter.Counter");
if (cntClass != null) {
try {
name = cntClass.getMethod("getName");
} catch (NoSuchMethodException e) {
}
try {
value = cntClass.getMethod("getValue");
} catch (NoSuchMethodException e) {
}
}
} catch (ClassNotFoundException e) {
}
GET_NAME = name;
GET_VALUE = value;
}
private final Object proxy;
public HotspotCounter(Object proxy) throws UnsupportedOperationException {
this.proxy = proxy;
if (GET_NAME == null || GET_VALUE == null) {
throw new UnsupportedOperationException();
}
try {
String k = (String) GET_NAME.invoke(proxy);
Object v = GET_VALUE.invoke(proxy);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new UnsupportedOperationException(e);
}
}
public String getName() {
try {
return (String) GET_NAME.invoke(proxy);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new IllegalStateException("Cannot be here");
}
}
public Object getValue() {
try {
return GET_VALUE.invoke(proxy);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new IllegalStateException("Cannot be here");
}
}
}
}