2 * Copyright (c) 2014 Brocade Communications Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.yangtools.util;
11 import static java.util.concurrent.TimeUnit.MICROSECONDS;
12 import static java.util.concurrent.TimeUnit.MILLISECONDS;
13 import static java.util.concurrent.TimeUnit.NANOSECONDS;
14 import static java.util.concurrent.TimeUnit.SECONDS;
16 import com.google.common.util.concurrent.AtomicDouble;
17 import java.text.DecimalFormat;
18 import java.text.DecimalFormatSymbols;
19 import java.util.Date;
20 import java.util.concurrent.TimeUnit;
21 import java.util.concurrent.atomic.AtomicLong;
24 * Class that calculates and tracks time duration statistics.
26 * @author Thomas Pantelis
28 public class DurationStatsTracker {
30 private static final DecimalFormat decimalFormat;
32 private final AtomicLong totalDurations = new AtomicLong();
33 private final AtomicLong longestDuration = new AtomicLong();
34 private volatile long timeOfLongestDuration;
35 private final AtomicLong shortestDuration = new AtomicLong(Long.MAX_VALUE);
36 private volatile long timeOfShortestDuration;
37 private final AtomicDouble averageDuration = new AtomicDouble();
40 final DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance();
41 symbols.setDecimalSeparator('.');
42 decimalFormat = new DecimalFormat("0.00", symbols);
46 * Add a duration to track.
49 * the duration in nanoseconds.
51 public void addDuration(long duration) {
53 double currentAve = averageDuration.get();
54 long currentTotal = totalDurations.get();
56 long newTotal = currentTotal + 1;
58 // Calculate moving cumulative average.
59 double newAve = currentAve * currentTotal / newTotal + (double) duration / (double) newTotal;
61 averageDuration.compareAndSet(currentAve, newAve);
62 totalDurations.compareAndSet(currentTotal, newTotal);
64 long longest = longestDuration.get();
65 if (duration > longest) {
66 if (longestDuration.compareAndSet(longest, duration)) {
67 timeOfLongestDuration = System.currentTimeMillis();
71 long shortest = shortestDuration.get();
72 if (duration < shortest) {
73 if (shortestDuration.compareAndSet(shortest, duration)) {
74 timeOfShortestDuration = System.currentTimeMillis();
80 * Returns the total number of tracked durations.
82 public long getTotalDurations() {
83 return totalDurations.get();
87 * Returns the longest duration in nanoseconds.
89 public long getLongestDuration() {
90 return longestDuration.get();
94 * Returns the shortest duration in nanoseconds.
96 public long getShortestDuration() {
97 long shortest = shortestDuration.get();
98 return shortest < Long.MAX_VALUE ? shortest : 0;
102 * Returns the average duration in nanoseconds.
104 public double getAverageDuration() {
105 return averageDuration.get();
109 * Returns the time stamp of the longest duration.
111 public long getTimeOfLongestDuration() {
112 return timeOfLongestDuration;
116 * Returns the time stamp of the shortest duration.
118 public long getTimeOfShortestDuration() {
119 return timeOfShortestDuration;
123 * Resets all statistics back to their defaults.
125 public void reset() {
126 totalDurations.set(0);
127 longestDuration.set(0);
128 timeOfLongestDuration = 0;
129 shortestDuration.set(Long.MAX_VALUE);
130 timeOfShortestDuration = 0;
131 averageDuration.set(0.0);
135 * Returns the average duration as a displayable String with units, e.g.
138 public String getDisplayableAverageDuration() {
139 return formatDuration(getAverageDuration(), 0);
143 * Returns the shortest duration as a displayable String with units and the
144 * date/time at which it occurred, e.g. "12.34 ms at 08/02/2014 12:30:24".
146 public String getDisplayableShortestDuration() {
147 return formatDuration(getShortestDuration(), getTimeOfShortestDuration());
151 * Returns the longest duration as a displayable String with units and the
152 * date/time at which it occurred, e.g. "12.34 ms at 08/02/2014 12:30:24".
154 public String getDisplayableLongestDuration() {
155 return formatDuration(getLongestDuration(), getTimeOfLongestDuration());
159 * Returns formatted value of number, e.g. "12.34". Always is used dot as
162 private static synchronized String formatDecimalValue(double value) {
163 return decimalFormat.format(value);
166 private String formatDuration(double duration, long timeStamp) {
167 TimeUnit unit = chooseUnit((long) duration);
168 double value = duration / NANOSECONDS.convert(1, unit);
170 return timeStamp > 0 ? String.format("%s %s at %3$tD %3$tT", formatDecimalValue(value), abbreviate(unit),
171 new Date(timeStamp)) : String.format("%s %s", formatDecimalValue(value), abbreviate(unit));
174 private static TimeUnit chooseUnit(long nanos) {
175 if (SECONDS.convert(nanos, NANOSECONDS) > 0) {
179 if (MILLISECONDS.convert(nanos, NANOSECONDS) > 0) {
183 if (MICROSECONDS.convert(nanos, NANOSECONDS) > 0) {
190 private static String abbreviate(TimeUnit unit) {
195 return "\u03bcs"; // μs