--- /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); + } +}