/* This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2016 Servoy BV This program is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program; if not, see http://www.gnu.org/licenses or write to the Free Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 */ package com.servoy.j2db.server.shared; import java.util.Collections; import java.util.HashMap; import java.util.Map; import com.servoy.j2db.server.shared.PerformanceData.TimeComparator; import com.servoy.j2db.util.SortedList; import com.servoy.j2db.util.UUID; /** * A class that can aggregate the results of multiple actions/operations. * * @author acostescu */ public class PerformanceAggregator { public static final int DEFAULT_MAX_ENTRIES_TO_KEEP_IN_PRODUCTION = 500; private SortedList<PerformanceTimingAggregate> sortedAggregates; private Map<String, PerformanceTimingAggregate> aggregatesByAction; protected final int maxEntriesToKeep; public PerformanceAggregator(int maxEntriesToKeep) { this.maxEntriesToKeep = maxEntriesToKeep; } /** * Creates a clone/copy. */ public PerformanceAggregator(PerformanceAggregator copy) { this.maxEntriesToKeep = copy.maxEntriesToKeep; if (copy.sortedAggregates != null) { sortedAggregates = new SortedList<PerformanceTimingAggregate>(new TimeComparator()); aggregatesByAction = new HashMap<String, PerformanceTimingAggregate>(maxEntriesToKeep); for (PerformanceTimingAggregate a : copy.sortedAggregates) { PerformanceTimingAggregate copyOfA = new PerformanceTimingAggregate(a); sortedAggregates.add(copyOfA); aggregatesByAction.put(a.getAction(), copyOfA); } } } /** * Please use {@link #startAction(String, long, int)} / {@link #endAction(UUID)} / {@link #intervalAction(UUID)} whenever possible instead. */ public synchronized void addTiming(String action, long interval_ms, long total_ms, int type, Map<String, PerformanceTimingAggregate> subActionTimings) { if (maxEntriesToKeep == IPerfomanceRegistry.OFF) return; if (aggregatesByAction == null) aggregatesByAction = new HashMap<String, PerformanceTimingAggregate>( maxEntriesToKeep > 0 ? maxEntriesToKeep : DEFAULT_MAX_ENTRIES_TO_KEEP_IN_PRODUCTION); if (sortedAggregates == null) sortedAggregates = new SortedList<PerformanceTimingAggregate>(new TimeComparator()); PerformanceTimingAggregate time = aggregatesByAction.get(action); if (time == null) { time = new PerformanceTimingAggregate(action, type, getSubActionMaxEntries()); aggregatesByAction.put(action, time); } // remove it because it will need to be sorted again after update sortedAggregates.remove(time); // update obj time.updateTime(interval_ms, total_ms); time.updateSubActionTimes(subActionTimings); // do sort again sortedAggregates.add(time); // do clean if (maxEntriesToKeep != IPerfomanceRegistry.UNLIMITED_ENTRIES && sortedAggregates.size() > maxEntriesToKeep) { PerformanceTimingAggregate old = sortedAggregates.remove(maxEntriesToKeep); aggregatesByAction.remove(old.getAction()); } } public synchronized void clear() { if (sortedAggregates != null) sortedAggregates.clear(); if (aggregatesByAction != null) aggregatesByAction.clear(); } public synchronized PerformanceTimingAggregate[] toArray() { return (sortedAggregates != null ? sortedAggregates.toArray(new PerformanceTimingAggregate[sortedAggregates.size()]) : new PerformanceTimingAggregate[0]); } public synchronized Map<String, PerformanceTimingAggregate> toMap() { return (aggregatesByAction != null ? Collections.unmodifiableMap(aggregatesByAction) : new HashMap<String, PerformanceTimingAggregate>()); } protected int getSubActionMaxEntries() { return maxEntriesToKeep == IPerfomanceRegistry.UNLIMITED_ENTRIES ? IPerfomanceRegistry.UNLIMITED_ENTRIES : Math.max(5, maxEntriesToKeep / 10); } }