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 java.util.Date;
17 import java.util.concurrent.TimeUnit;
18 import java.util.concurrent.atomic.AtomicLong;
20 import com.google.common.util.concurrent.AtomicDouble;
23 * Class that calculates and tracks time duration statistics.
25 * @author Thomas Pantelis
27 public class DurationStatsTracker {
29 private final AtomicLong totalDurations = new AtomicLong();
30 private final AtomicLong longestDuration = new AtomicLong();
31 private volatile long timeOfLongestDuration;
32 private final AtomicLong shortestDuration = new AtomicLong(Long.MAX_VALUE);
33 private volatile long timeOfShortestDuration;
34 private final AtomicDouble averageDuration = new AtomicDouble();
37 * Add a duration to track.
39 * @param duration the duration in nanoseconds.
41 public void addDuration(long duration) {
43 double currentAve = averageDuration.get();
44 long currentTotal = totalDurations.get();
46 long newTotal = currentTotal + 1;
48 // Calculate moving cumulative average.
49 double newAve = currentAve * (double)currentTotal / (double)newTotal + (double)duration / (double)newTotal;
51 averageDuration.compareAndSet(currentAve, newAve);
52 totalDurations.compareAndSet(currentTotal, newTotal);
54 long longest = longestDuration.get();
55 if( duration > longest ) {
56 if(longestDuration.compareAndSet( longest, duration )) {
57 timeOfLongestDuration = System.currentTimeMillis();
61 long shortest = shortestDuration.get();
62 if( duration < shortest ) {
63 if(shortestDuration.compareAndSet( shortest, duration )) {
64 timeOfShortestDuration = System.currentTimeMillis();
70 * Returns the total number of tracked durations.
72 public long getTotalDurations() {
73 return totalDurations.get();
77 * Returns the longest duration in nanoseconds.
79 public long getLongestDuration() {
80 return longestDuration.get();
84 * Returns the shortest duration in nanoseconds.
86 public long getShortestDuration() {
87 long shortest = shortestDuration.get();
88 return shortest < Long.MAX_VALUE ? shortest : 0;
92 * Returns the average duration in nanoseconds.
94 public double getAverageDuration() {
95 return averageDuration.get();
99 * Returns the time stamp of the longest duration.
101 public long getTimeOfLongestDuration() {
102 return timeOfLongestDuration;
106 * Returns the time stamp of the shortest duration.
108 public long getTimeOfShortestDuration() {
109 return timeOfShortestDuration;
113 * Resets all statistics back to their defaults.
115 public void reset() {
116 totalDurations.set(0);
117 longestDuration.set(0);
118 timeOfLongestDuration = 0;
119 shortestDuration.set(Long.MAX_VALUE);
120 timeOfShortestDuration = 0;
121 averageDuration.set(0.0);
125 * Returns the average duration as a displayable String with units, e.g. "12.34 ms".
127 public String getDisplayableAverageDuration() {
128 return formatDuration(getAverageDuration(), 0);
132 * Returns the shortest duration as a displayable String with units and the date/time at
133 * which it occurred, e.g. "12.34 ms at 08/02/2014 12:30:24".
135 public String getDisplayableShortestDuration() {
136 return formatDuration(getShortestDuration(), getTimeOfShortestDuration());
140 * Returns the longest duration as a displayable String with units and the date/time at
141 * which it occurred, e.g. "12.34 ms at 08/02/2014 12:30:24".
143 public String getDisplayableLongestDuration() {
144 return formatDuration(getLongestDuration(), getTimeOfLongestDuration());
147 private String formatDuration(double duration, long timeStamp) {
148 TimeUnit unit = chooseUnit((long)duration);
149 double value = duration / NANOSECONDS.convert(1, unit);
150 return timeStamp > 0 ?
151 String.format("%.4g %s at %3$tD %3$tT", value, abbreviate(unit), new Date(timeStamp)) :
152 String.format("%.4g %s", value, abbreviate(unit));
155 private static TimeUnit chooseUnit(long nanos) {
156 if(SECONDS.convert(nanos, NANOSECONDS) > 0) {
160 if(MILLISECONDS.convert(nanos, NANOSECONDS) > 0) {
164 if(MICROSECONDS.convert(nanos, NANOSECONDS) > 0) {
171 private static String abbreviate(TimeUnit unit) {
176 return "\u03bcs"; // μs