1 /* 2 * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved. 3 * 4 * This file is part of the Lock Contention Tracing Subsystem for the HotSpot 5 * Virtual Machine, which is developed at Christian Doppler Laboratory on 6 * Monitoring and Evolution of Very-Large-Scale Software Systems. Please 7 * contact us at <http://mevss.jku.at/> if you need additional information 8 * or have any questions. 9 * 10 * This code is free software; you can redistribute it and/or modify it 11 * under the terms of the GNU General Public License version 2 only, as 12 * published by the Free Software Foundation. 13 * 14 * This code is distributed in the hope that it will be useful, but WITHOUT 15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 17 * version 2 for more details (a copy is included in the LICENSE file that 18 * accompanied this code). 19 * 20 * You should have received a copy of the GNU General Public License version 21 * 2 along with this work. If not, see <http://www.gnu.org/licenses/>. 22 * 23 */ 24 package sun.evtracing.processing.statistics.aggregator; 25 26 import java.util.ArrayList; 27 import java.util.Comparator; 28 import java.util.HashMap; 29 import java.util.Iterator; 30 import java.util.Map; 31 import java.util.Map.Entry; 32 33 import sun.evtracing.processing.statistics.metadata.Contention; 34 35 public abstract class ComplexAggregator<I, O> extends Aggregator { 36 protected Map<I, Aggregator> children = new HashMap<>(); 37 38 ComplexAggregator(AggregatorFactory<? extends ComplexAggregator<I, O>> factory) { 39 super(factory); 40 } 41 42 ComplexAggregator(ComplexAggregator<I, O> x, ComplexAggregator<I, O> y) { 43 super(x, y); 44 45 children.putAll(x.children); 46 for (Entry<I, Aggregator> e : y.children.entrySet()) { 47 children.merge(e.getKey(), e.getValue(), (u, v) -> { 48 u.merge(); 49 v.merge(); 50 return u.factory().mergeChecked(u, v); 51 }); 52 } 53 } 54 55 @Override 56 public abstract Map<O, Aggregator> children(); 57 58 Aggregator createChild() { 59 return factory().nextFactory().create(); 60 } 61 62 void submitToChildren(I key, Contention c) { 63 Aggregator child = children.computeIfAbsent(key, x -> createChild()); 64 child.submit(c); 65 } 66 67 @Override 68 public void merge() { 69 filterDuration(); 70 for (Aggregator child : children.values()) { 71 child.merge(); 72 } 73 } 74 75 private void filterDuration() { 76 AggregationConfiguration config = factory().configuration(); 77 if (config.isAbsoluteDurationFilterEnabled() || config.isRelativeDurationFilterEnabled()) { 78 long threshold; 79 if (config.isAbsoluteDurationFilterEnabled() && config.isRelativeDurationFilterEnabled()) { 80 threshold = Math.max((long) (statistic().getSum() * config.relativeDurationFilterThreshold()), config.absoluteDurationFilterThreshold()); 81 } else if (config.isAbsoluteDurationFilterEnabled()) { 82 threshold = config.absoluteDurationFilterThreshold(); 83 } else { 84 threshold = (long) (statistic().getSum() * config.relativeDurationFilterThreshold()); 85 } 86 87 Map<I, Aggregator> affected = new HashMap<>(); 88 Iterator<Entry<I, Aggregator>> it = children.entrySet().iterator(); 89 while (it.hasNext()) { 90 Map.Entry<I, Aggregator> entry = it.next(); 91 if (entry.getValue().statistic().getSum() < threshold) { 92 affected.put(entry.getKey(), entry.getValue()); 93 it.remove(); 94 } 95 } 96 97 if (affected.size() > 1) { 98 Aggregator merged = affected.values().stream().reduce((x, y) -> x.factory().mergeChecked(x, y)).get(); 99 children.put(createDurationFilteredChild(), merged); 100 } else { 101 // don't filter if only one child would be affected 102 children.putAll(affected); 103 } 104 } 105 } 106 107 protected abstract I createDurationFilteredChild(); 108 109 void mergeChildren(Comparator<? super I> cmp) { 110 ArrayList<I> sorted = new ArrayList<>(children.keySet()); 111 sorted.sort(cmp); 112 113 Map<I, Aggregator> merged = new HashMap<>(); 114 I current = null; 115 Aggregator currentChild = null; 116 for (I next : sorted) { 117 Aggregator nextChild = children.get(next); 118 if (current != null) { 119 if (cmp.compare(current, next) == 0) { 120 currentChild = currentChild.factory().mergeChecked(currentChild, nextChild); 121 } else { 122 merged.put(current, currentChild); 123 current = next; 124 currentChild = nextChild; 125 } 126 } else { 127 current = next; 128 currentChild = nextChild; 129 } 130 } 131 if (current != null) { 132 merged.put(current, currentChild); 133 } 134 children = merged; 135 filterDuration(); 136 for (Aggregator child : children.values()) { 137 child.merge(); 138 } 139 } 140 }