--- /dev/null 2016-10-25 08:46:44.038854975 +0200
+++ new/src/share/classes/sun/evtracing/processing/statistics/TraceEventStatisticsHandler.java 2016-10-25 10:40:51.780805730 +0200
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ *
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see .
+ *
+ */
+package sun.evtracing.processing.statistics;
+
+import java.util.HashMap;
+import java.util.Map;
+import sun.evtracing.parser.GroupEvent;
+import sun.evtracing.parser.MonitorContendedEnterEvent;
+import sun.evtracing.parser.MonitorContendedEnteredEvent;
+import sun.evtracing.parser.MonitorContendedExitedEvent;
+import sun.evtracing.parser.MonitorDeflateEvent;
+import sun.evtracing.parser.MonitorInflateEvent;
+import sun.evtracing.parser.ThreadInterruptEvent;
+import sun.evtracing.parser.ThreadParkBeginEvent;
+import sun.evtracing.parser.ThreadParkEndEvent;
+import sun.evtracing.parser.ThreadUnparkEvent;
+import sun.evtracing.parser.VMEndEvent;
+import sun.evtracing.parser.metadata.JavaThread;
+import sun.evtracing.parser.metadata.MethodFilter;
+import sun.evtracing.processing.AbstractTraceEventHandler;
+import sun.evtracing.processing.Sanity;
+import sun.evtracing.processing.statistics.aggregator.AggregationConfiguration;
+import sun.evtracing.processing.statistics.aggregator.Aggregator;
+import sun.evtracing.processing.statistics.aggregator.BlockerClassAggregator;
+import sun.evtracing.processing.statistics.aggregator.BlockerClassAggregatorFactory;
+import sun.evtracing.processing.statistics.aggregator.ContendingSiteAggregatorFactory;
+import sun.evtracing.processing.statistics.aggregator.ContendingThreadAggregator;
+import sun.evtracing.processing.statistics.aggregator.ContendingThreadAggregatorFactory;
+import sun.evtracing.processing.statistics.aggregator.ContentionProcessor;
+import sun.evtracing.processing.statistics.aggregator.LeafAggregatorFactory;
+import sun.evtracing.processing.statistics.aggregator.MultiAggregator;
+import sun.evtracing.processing.statistics.aggregator.NegativeDurationContentionFilter;
+import sun.evtracing.processing.statistics.aggregator.OwnerSiteAggregatorFactory;
+import sun.evtracing.processing.statistics.metadata.JavaClassStack;
+
+public class TraceEventStatisticsHandler extends AbstractTraceEventHandler {
+
+ private final Map parkAnalyser = new HashMap<>();
+ private final ParkBlockerAnalyser parkBlockerDispatcher;
+ private final Map monitorAnalysers = new HashMap<>();
+ private final ContendingThreadAggregator contendingThreadAggregator;
+ private final BlockerClassAggregator blockerClassAggregator;
+ private final MultiAggregator aggregators = new MultiAggregator();
+ private final ContentionProcessor processor;
+
+ public TraceEventStatisticsHandler() {
+ AggregationConfiguration configuration = new AggregationConfiguration(MethodFilter.NO_FILTER);
+ contendingThreadAggregator = new ContendingThreadAggregatorFactory(new LeafAggregatorFactory(configuration), configuration).create();
+ ContendingSiteAggregatorFactory factories = new ContendingSiteAggregatorFactory(new OwnerSiteAggregatorFactory(new LeafAggregatorFactory(configuration), configuration), configuration);
+ blockerClassAggregator = new BlockerClassAggregatorFactory(factories, configuration).create();
+ aggregators.add(contendingThreadAggregator);
+ aggregators.add(blockerClassAggregator);
+ processor = new NegativeDurationContentionFilter(aggregators);
+ parkBlockerDispatcher = new ParkBlockerDispatcher(processor);
+ }
+
+ private final Statistics result = new Statistics() {
+ @Override
+ public Map contendingThreads() {
+ return contendingThreadAggregator.children();
+ }
+
+ @Override
+ public Map blockerClasses() {
+ return blockerClassAggregator.children();
+ }
+ };
+
+ public Statistics result() {
+ return result;
+ }
+
+ @Override
+ public void endVM(VMEndEvent event) {
+ processor.merge();
+
+ Sanity.printCollectedWarnings();
+ }
+
+ private ParkAnalyser getOrCreateParkAnalyser(long thread) {
+ return parkAnalyser.computeIfAbsent(thread, t -> new ParkAnalyser(parkBlockerDispatcher));
+ }
+
+ @Override
+ public void threadParkBegin(ThreadParkBeginEvent event) {
+ ParkAnalyser pa = getOrCreateParkAnalyser(event.thread().identifier());
+ pa.begin(event);
+ }
+
+ @Override
+ public void threadParkEnd(ThreadParkEndEvent event) {
+ ParkAnalyser pa = getOrCreateParkAnalyser(event.thread().identifier());
+ pa.end(event);
+ }
+
+ @Override
+ public void threadUnpark(ThreadUnparkEvent event) {
+ ParkAnalyser pa = getOrCreateParkAnalyser(event.unparkedThread().identifier());
+ pa.unpark(event);
+ }
+
+ @Override
+ public void threadInterrupt(ThreadInterruptEvent event) {
+ ParkAnalyser pa = getOrCreateParkAnalyser(event.affectedThread().identifier());
+ pa.interrupt(event);
+ }
+
+ @Override
+ public void group(GroupEvent event) {
+ ParkAnalyser pa = getOrCreateParkAnalyser(event.thread().identifier());
+ pa.group(event);
+ }
+
+ //
+ // Monitors
+ //
+
+ // NOTE: we are guaranteed only that we get events for a particular monitor
+ // in the correct order. However, events of one monitor can be
+ // interleaved with events of other monitors, and events of the same
+ // thread are no longer in the order in which they were written.
+
+ @Override
+ public void monitorInflate(MonitorInflateEvent event) {
+ assert !monitorAnalysers.containsKey(event.monitor());
+ MonitorAnalyser ma = MonitorAnalyser.forInflate(event, processor);
+ monitorAnalysers.put(event.monitor(), ma);
+ }
+
+ @Override
+ public void monitorContendedEnter(MonitorContendedEnterEvent event) {
+ MonitorAnalyser ma = monitorAnalysers.get(event.monitor());
+ ma.enter(event);
+ }
+
+ @Override
+ public void monitorContendedEntered(MonitorContendedEnteredEvent event) {
+ MonitorAnalyser ma = monitorAnalysers.get(event.monitor());
+ ma.entered(event);
+ }
+
+ @Override
+ public void monitorContendedExited(MonitorContendedExitedEvent event) {
+ MonitorAnalyser ma = monitorAnalysers.get(event.monitor());
+ ma.exited(event);
+ }
+
+ @Override
+ public void monitorDeflate(MonitorDeflateEvent event) {
+ MonitorAnalyser ma = monitorAnalysers.remove(event.monitor());
+ ma.deflate(event);
+ }
+}