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
8 package org.opendaylight.yangtools.util;
10 import static java.util.concurrent.TimeUnit.MICROSECONDS;
11 import static java.util.concurrent.TimeUnit.MILLISECONDS;
12 import static java.util.concurrent.TimeUnit.NANOSECONDS;
13 import static java.util.concurrent.TimeUnit.SECONDS;
15 import com.google.common.annotations.Beta;
16 import java.text.DecimalFormat;
17 import java.text.DecimalFormatSymbols;
18 import java.util.Date;
19 import java.util.concurrent.TimeUnit;
20 import org.slf4j.Logger;
21 import org.slf4j.LoggerFactory;
24 * Abstract class that calculates and tracks time duration statistics.
26 * @author Thomas Pantelis
27 * @author Robert Varga
30 public abstract class DurationStatisticsTracker {
31 private static final Logger LOG = LoggerFactory.getLogger(DurationStatisticsTracker.class);
32 private static final DecimalFormat DECIMAL_FORMAT;
35 final DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance();
36 symbols.setDecimalSeparator('.');
37 DECIMAL_FORMAT = new DecimalFormat("0.00", symbols);
41 * Create a concurrent {@link DurationStatisticsTracker}, which performs well in very contended environments.
43 * @return A new instance.
45 public static DurationStatisticsTracker createConcurrent() {
46 return new ConcurrentDurationStatisticsTracker();
50 * Create a synchronized {@link DurationStatisticsTracker}, which performs well in non-contended environments.
52 * @return A new instance.
54 public static DurationStatisticsTracker createSynchronized() {
55 return new SynchronizedDurationStatsTracker();
59 * Add a duration to track.
61 * @param duration non-negative duration in nanoseconds.
63 public abstract void addDuration(long duration);
66 * Returns the average duration in nanoseconds.
68 * @return average duration in nanoseconds.
70 public abstract double getAverageDuration();
73 * Returns the total number of tracked durations.
75 * @return Total number of measurements accumulated since last {@link #reset()}.
77 public abstract long getTotalDurations();
80 * Resets all statistics back to their defaults.
82 public abstract void reset();
85 * Returns the longest duration in nanoseconds.
87 * @return the longest duration in nanoseconds.
89 public final long getLongestDuration() {
90 return getDuration(getLongest());
94 * Returns the shortest duration in nanoseconds.
96 * @return the shortest duration in nanoseconds.
98 public final long getShortestDuration() {
99 return getDuration(getShortest());
103 * Returns the average duration as a displayable String with units, e.g. {@code 12.34 ms}.
105 * @return the average duration in human-readable form.
107 public final String getDisplayableAverageDuration() {
108 return formatDuration(getAverageDuration(), null);
112 * Returns the longest duration as a displayable String with units and the date/time at which it occurred, e.g.
113 * {@code 12.34 ms at 08/02/2014 12:30:24}.
115 * @return The longest duration and when it has occurred in human-readable form.
117 public final String getDisplayableLongestDuration() {
118 return formatDuration(getLongest());
122 * Returns the shortest duration as a displayable String with units and the date/time at which it occurred, e.g.
123 * {@code 12.34 ms at 08/02/2014 12:30:24}.
125 * @return The shortest duration and when it has occurred in human-readable form.
127 public final String getDisplayableShortestDuration() {
128 return formatDuration(getShortest());
132 * Returns the time stamp of the longest duration.
134 * @return the time stamp of the longest duration.
136 public final long getTimeOfLongestDuration() {
137 return getTimeMillis(getLongest());
141 * Returns the time stamp of the shortest duration.
143 * @return the time stamp of the shortest duration.
145 public final long getTimeOfShortestDuration() {
146 return getTimeMillis(getShortest());
150 * Get the shortest recorded duration and the time when it was recorded.
152 * @return Duration and timestamp.
154 abstract DurationWithTime getShortest();
157 * Get the longest recorded duration and the time when it was recorded.
159 * @return Duration and timestamp.
161 abstract DurationWithTime getLongest();
164 * Returns formatted value of number, e.g. "12.34". Always is used dot as decimal separator.
166 private static synchronized String formatDecimalValue(final double value) {
167 return DECIMAL_FORMAT.format(value);
170 private static long getDuration(final DurationWithTime current) {
171 return current == null ? 0L : current.getDuration();
174 private static long getTimeMillis(final DurationWithTime current) {
175 return current == null ? 0L : current.getTimeMillis();
178 private static String formatDuration(final double duration, final Long timeStamp) {
179 final TimeUnit unit = chooseUnit((long) duration);
180 final double value = duration / NANOSECONDS.convert(1, unit);
182 final StringBuilder sb = new StringBuilder();
183 sb.append(formatDecimalValue(value)).append(' ').append(abbreviate(unit));
185 if (timeStamp != null) {
186 sb.append(String.format(" at %1$tD %1$tT", new Date(timeStamp)));
189 return sb.toString();
192 private static String formatDuration(final DurationWithTime current) {
193 if (current == null) {
194 return formatDuration(0, null);
196 return formatDuration(current.getDuration(), current.getTimeMillis());
199 private static TimeUnit chooseUnit(final long nanos) {
200 // TODO: this could be inlined, as we are doing needless divisions
201 if (NANOSECONDS.toSeconds(nanos) > 0) {
204 if (NANOSECONDS.toMillis(nanos) > 0) {
207 if (NANOSECONDS.toMicros(nanos) > 0) {
213 private static String abbreviate(final TimeUnit unit) {
230 LOG.warn("Unhandled time unit {}", unit);