diff --git a/jvm/jfr-annotations/src/main/java/org/quickperf/jvm/jmc/value/DisplayJvmProfilingValueVerifier.java b/jvm/jfr-annotations/src/main/java/org/quickperf/jvm/jmc/value/DisplayJvmProfilingValueVerifier.java index fdabd0ee..595ec26f 100644 --- a/jvm/jfr-annotations/src/main/java/org/quickperf/jvm/jmc/value/DisplayJvmProfilingValueVerifier.java +++ b/jvm/jfr-annotations/src/main/java/org/quickperf/jvm/jmc/value/DisplayJvmProfilingValueVerifier.java @@ -46,6 +46,7 @@ public PerfIssue verifyPerfIssue(ProfileJvm annotation, JfrEventsMeasure jfrEven String insideTlabSum = ALLOC_INSIDE_TLAB_SUM.formatAsString(jfrEvents); String outsideTlabSum = ALLOC_OUTSIDE_TLAB_SUM.formatAsString(jfrEvents); String allocationRate = ALLOCATION_RATE.formatAsString(jfrEvents); + String allocatedClasses = ALLOCATED_CLASSES.formatAsString(jfrEvents); String totalGcPause = TOTAL_GC_PAUSE.formatAsString(jfrEvents); String gcPause = LONGEST_GC_PAUSE.formatAsString(jfrEvents); @@ -89,6 +90,7 @@ public PerfIssue verifyPerfIssue(ProfileJvm annotation, JfrEventsMeasure jfrEven + " Inside TLAB : " + fifteenLength.adapt(insideTlabSum) + "| " + twentyNineLength.adapt("Longest GC pause: " + gcPause) + "| Error : " + errorCount + LINE_SEPARATOR + " Outside TLAB: " + fifteenLength.adapt(outsideTlabSum) + "| " + twentyNineLength.adapt("Young: " + youngGcCollection) + "| Throwable: " + throwablesCount + LINE_SEPARATOR + " Allocation rate: " + twelveLength.adapt(allocationRate) + "| " + twentyNineLength.adapt("Old : " + oldGcCollection) + "|" + LINE_SEPARATOR + + " " + allocatedClasses + LINE_SEPARATOR + LINE + thirtyLength.adapt(" COMPILATION") + "| " + "CODE CACHE" + LINE_SEPARATOR + thirtyLength.adapt(" Number : " + compilationsCount) + "| " + codeCacheFullCount + LINE_SEPARATOR diff --git a/jvm/jfr-annotations/src/main/java/org/quickperf/jvm/jmc/value/ProfilingInfo.java b/jvm/jfr-annotations/src/main/java/org/quickperf/jvm/jmc/value/ProfilingInfo.java index 549626b8..b5137510 100644 --- a/jvm/jfr-annotations/src/main/java/org/quickperf/jvm/jmc/value/ProfilingInfo.java +++ b/jvm/jfr-annotations/src/main/java/org/quickperf/jvm/jmc/value/ProfilingInfo.java @@ -16,10 +16,14 @@ import org.openjdk.jmc.common.item.IItemCollection; import org.openjdk.jmc.common.unit.IQuantity; import org.openjdk.jmc.flightrecorder.jdk.JdkAggregators; +import org.quickperf.jvm.jmc.value.allocationbyclass.AllocationByClassFormatter; +import org.quickperf.jvm.jmc.value.allocationbyclass.AllocationByClassResult; +import org.quickperf.jvm.jmc.value.allocationbyclass.AllocationByClassResultRetriever; import org.quickperf.jvm.jmc.value.allocationrate.AllocationRate; import org.quickperf.jvm.jmc.value.allocationrate.AllocationRateFormatter; import org.quickperf.jvm.jmc.value.allocationrate.AllocationRateRetriever; +@SuppressWarnings("rawtypes") public enum ProfilingInfo { TOTAL_GC_PAUSE { @@ -284,7 +288,8 @@ public String getLabel() { return getLabel(JdkAggregators.OS_VERSION, String.class); } - }, + } + , ALLOCATION_RATE { @Override public String formatAsString(IItemCollection jfrEvents) { @@ -300,6 +305,21 @@ public String formatAsString(IItemCollection jfrEvents) { public String getLabel() { return "Allocation Rate"; } + } + , + ALLOCATED_CLASSES { + @Override + public String formatAsString(IItemCollection jfrEvents) { + AllocationByClassResult result = AllocationByClassResultRetriever.INSTANCE + .extractAllocationByClassResultFrom(jfrEvents); + + return AllocationByClassFormatter.INSTANCE.format(result); + } + + @Override + public String getLabel() { + return "Allocated Classes"; + } }; public abstract String formatAsString(IItemCollection jfrEvents); diff --git a/jvm/jfr-annotations/src/main/java/org/quickperf/jvm/jmc/value/allocationbyclass/AllocationByClassFormatter.java b/jvm/jfr-annotations/src/main/java/org/quickperf/jvm/jmc/value/allocationbyclass/AllocationByClassFormatter.java new file mode 100644 index 00000000..2f89be4a --- /dev/null +++ b/jvm/jfr-annotations/src/main/java/org/quickperf/jvm/jmc/value/allocationbyclass/AllocationByClassFormatter.java @@ -0,0 +1,25 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + * + * Copyright 2019-2020 the original author or authors. + */ + +package org.quickperf.jvm.jmc.value.allocationbyclass; + +import org.quickperf.jvm.jmcrule.HtmlToPlainTextTransformer; + +public class AllocationByClassFormatter { + public static final AllocationByClassFormatter INSTANCE = new AllocationByClassFormatter(); + + private AllocationByClassFormatter() {} + + public String format(AllocationByClassResult result) { + final String shortDescription = result.getResult().getShortDescription(); + return HtmlToPlainTextTransformer.INSTANCE.convertHtmlToPlainText(shortDescription); + } +} diff --git a/jvm/jfr-annotations/src/main/java/org/quickperf/jvm/jmc/value/allocationbyclass/AllocationByClassResult.java b/jvm/jfr-annotations/src/main/java/org/quickperf/jvm/jmc/value/allocationbyclass/AllocationByClassResult.java new file mode 100644 index 00000000..b411d5da --- /dev/null +++ b/jvm/jfr-annotations/src/main/java/org/quickperf/jvm/jmc/value/allocationbyclass/AllocationByClassResult.java @@ -0,0 +1,27 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + * + * Copyright 2019-2020 the original author or authors. + */ + +package org.quickperf.jvm.jmc.value.allocationbyclass; + +import org.openjdk.jmc.flightrecorder.rules.Result; + +public class AllocationByClassResult { + + private final Result result; + + public AllocationByClassResult(Result result) { + this.result = result; + } + + public Result getResult() { + return result; + } +} diff --git a/jvm/jfr-annotations/src/main/java/org/quickperf/jvm/jmc/value/allocationbyclass/AllocationByClassResultRetriever.java b/jvm/jfr-annotations/src/main/java/org/quickperf/jvm/jmc/value/allocationbyclass/AllocationByClassResultRetriever.java new file mode 100644 index 00000000..eb855c36 --- /dev/null +++ b/jvm/jfr-annotations/src/main/java/org/quickperf/jvm/jmc/value/allocationbyclass/AllocationByClassResultRetriever.java @@ -0,0 +1,41 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + * + * Copyright 2019-2020 the original author or authors. + */ + +package org.quickperf.jvm.jmc.value.allocationbyclass; + +import org.openjdk.jmc.common.item.IItemCollection; +import org.openjdk.jmc.common.util.IPreferenceValueProvider; +import org.openjdk.jmc.flightrecorder.rules.Result; +import org.openjdk.jmc.flightrecorder.rules.jdk.memory.AllocationByClassRule; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.RunnableFuture; + +public class AllocationByClassResultRetriever { + public static final AllocationByClassResultRetriever INSTANCE = new AllocationByClassResultRetriever(); + private static final AllocationByClassRule allocationByClassRule = new AllocationByClassRule(); + private static final Result NO_RESULT = new Result(allocationByClassRule, 0d, ""); + + private AllocationByClassResultRetriever() {} + + public AllocationByClassResult extractAllocationByClassResultFrom(IItemCollection jfrEvents) { + RunnableFuture allocationByClassRuleFuture = + allocationByClassRule.evaluate(jfrEvents, IPreferenceValueProvider.DEFAULT_VALUES); + allocationByClassRuleFuture.run(); + Result result; + try { + result = allocationByClassRuleFuture.get(); + } catch (InterruptedException | ExecutionException e) { + result = NO_RESULT; + } + return new AllocationByClassResult(result); + } +} diff --git a/jvm/jfr-annotations/src/main/java/org/quickperf/jvm/jmcrule/HtmlToPlainTextTransformer.java b/jvm/jfr-annotations/src/main/java/org/quickperf/jvm/jmcrule/HtmlToPlainTextTransformer.java index 5f8e155b..ec7311aa 100644 --- a/jvm/jfr-annotations/src/main/java/org/quickperf/jvm/jmcrule/HtmlToPlainTextTransformer.java +++ b/jvm/jfr-annotations/src/main/java/org/quickperf/jvm/jmcrule/HtmlToPlainTextTransformer.java @@ -15,7 +15,7 @@ import org.jsoup.examples.HtmlToPlainText; import org.jsoup.nodes.Document; -class HtmlToPlainTextTransformer { +public class HtmlToPlainTextTransformer { public static final HtmlToPlainTextTransformer INSTANCE = new HtmlToPlainTextTransformer(); diff --git a/testng/testng-jvm-test/src/test/java/org/quickperf/testng/jvm/jmc/AllocatedClassesProfileJVMTest.java b/testng/testng-jvm-test/src/test/java/org/quickperf/testng/jvm/jmc/AllocatedClassesProfileJVMTest.java new file mode 100644 index 00000000..3abe6b55 --- /dev/null +++ b/testng/testng-jvm-test/src/test/java/org/quickperf/testng/jvm/jmc/AllocatedClassesProfileJVMTest.java @@ -0,0 +1,41 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + * + * Copyright 2019-2020 the original author or authors. + */ + +package org.quickperf.testng.jvm.jmc; + +import org.quickperf.jvm.jfr.annotation.ProfileJvm; +import org.testng.annotations.Test; + +import java.util.ArrayList; +import java.util.List; + +public class AllocatedClassesProfileJVMTest { + + @ProfileJvm + @Test + public void mostAllocatedClassesProfileJVMAnnotation() { + IntegerAccumulator integerAccumulator = new IntegerAccumulator(); + integerAccumulator.accumulateInteger(500_000); + } + + private static class IntegerAccumulator { + + private List integerList; + + void accumulateInteger(int numberOfIntegers) { + integerList = new ArrayList<>(numberOfIntegers); + for (int i = 1; i <= numberOfIntegers; i++) { + integerList.add(i); + } + } + + } +}