All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opendaylight.yangtools.util.DurationStatisticsTracker Maven / Gradle / Ivy

There is a newer version: 14.0.4
Show newest version
/*
 * Copyright (c) 2014 Brocade Communications Systems, Inc. and others.  All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 */
package org.opendaylight.yangtools.util;

import static java.util.concurrent.TimeUnit.MICROSECONDS;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;

import com.google.common.annotations.Beta;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * Abstract class that calculates and tracks time duration statistics.
 *
 * @author Thomas Pantelis
 * @author Robert Varga
 */
@Beta
public abstract class DurationStatisticsTracker {
    private static final DecimalFormat DECIMAL_FORMAT;

    static {
        final DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance();
        symbols.setDecimalSeparator('.');
        DECIMAL_FORMAT = new DecimalFormat("0.00", symbols);
    }

    /**
     * Create a concurrent {@link DurationStatisticsTracker}, which performs well in very contended environments.
     *
     * @return A new instance.
     */
    public static DurationStatisticsTracker createConcurrent() {
        return new ConcurrentDurationStatisticsTracker();
    }

    /**
     * Create a synchronized {@link DurationStatisticsTracker}, which performs well in non-contended environments.
     *
     * @return A new instance.
     */
    public static DurationStatisticsTracker createSynchronized() {
        return new SynchronizedDurationStatsTracker();
    }

    /**
     * Add a duration to track.
     *
     * @param duration non-negative duration in nanoseconds.
     */
    public abstract void addDuration(long duration);

    /**
     * Returns the average duration in nanoseconds.
     *
     * @return average duration in nanoseconds.
     */
    public abstract double getAverageDuration();

    /**
     * Returns the total number of tracked durations.
     *
     * @return Total number of measurements accumulated since last {@link #reset()}.
     */
    public abstract long getTotalDurations();

    /**
     * Resets all statistics back to their defaults.
     */
    public abstract void reset();

    /**
     * Returns the longest duration in nanoseconds.
     *
     * @return the longest duration in nanoseconds.
     */
    public final long getLongestDuration() {
        return getDuration(getLongest());
    }

    /**
     * Returns the shortest duration in nanoseconds.
     *
     * @return the shortest duration in nanoseconds.
     */
    public final long getShortestDuration() {
        return getDuration(getShortest());
    }

    /**
     * Returns the average duration as a displayable String with units, e.g. {@code 12.34 ms}.
     *
     * @return the average duration in human-readable form.
     */
    public final String getDisplayableAverageDuration() {
        return formatDuration(getAverageDuration(), null);
    }

    /**
     * Returns the longest duration as a displayable String with units and the date/time at which it occurred, e.g.
     * {@code 12.34 ms at 08/02/2014 12:30:24}.
     *
     * @return The longest duration and when it has occurred in human-readable form.
     */
    public final String getDisplayableLongestDuration() {
        return formatDuration(getLongest());
    }

    /**
     * Returns the shortest duration as a displayable String with units and the date/time at which it occurred, e.g.
     * {@code 12.34 ms at 08/02/2014 12:30:24}.
     *
     * @return The shortest duration and when it has occurred in human-readable form.
     */
    public final String getDisplayableShortestDuration() {
        return formatDuration(getShortest());
    }

    /**
     * Returns the time stamp of the longest duration.
     *
     * @return the time stamp of the longest duration.
     */
    public final long getTimeOfLongestDuration() {
        return getTimeMillis(getLongest());
    }

    /**
     * Returns the time stamp of the shortest duration.
     *
     * @return the time stamp of the shortest duration.
     */
    public final long getTimeOfShortestDuration() {
        return getTimeMillis(getShortest());
    }

    /**
     * Get the shortest recorded duration and the time when it was recorded.
     *
     * @return Duration and timestamp.
     */
    abstract DurationWithTime getShortest();

    /**
     * Get the longest recorded duration and the time when it was recorded.
     *
     * @return Duration and timestamp.
     */
    abstract DurationWithTime getLongest();

    /**
     * Returns formatted value of number, e.g. "12.34". Always is used dot as decimal separator.
     */
    private static synchronized String formatDecimalValue(final double value) {
        return DECIMAL_FORMAT.format(value);
    }

    private static long getDuration(final DurationWithTime current) {
        return current == null ? 0L : current.duration();
    }

    private static long getTimeMillis(final DurationWithTime current) {
        return current == null ? 0L : current.timeMillis();
    }

    private static String formatDuration(final double duration, final Long timeStamp) {
        final TimeUnit unit = chooseUnit((long) duration);
        final double value = duration / NANOSECONDS.convert(1, unit);

        final StringBuilder sb = new StringBuilder();
        sb.append(formatDecimalValue(value)).append(' ').append(abbreviate(unit));

        if (timeStamp != null) {
            sb.append(String.format(" at %1$tD %1$tT", new Date(timeStamp)));
        }

        return sb.toString();
    }

    private static String formatDuration(final DurationWithTime current) {
        return current == null ? formatDuration(0, null) : formatDuration(current.duration(), current.timeMillis());
    }

    private static TimeUnit chooseUnit(final long nanos) {
        // TODO: this could be inlined, as we are doing needless divisions
        if (NANOSECONDS.toSeconds(nanos) > 0) {
            return SECONDS;
        }
        if (NANOSECONDS.toMillis(nanos) > 0) {
            return MILLISECONDS;
        }
        if (NANOSECONDS.toMicros(nanos) > 0) {
            return MICROSECONDS;
        }
        return NANOSECONDS;
    }

    private static String abbreviate(final TimeUnit unit) {
        return switch (unit) {
            case NANOSECONDS -> "ns";
            case MICROSECONDS -> "μs";
            case MILLISECONDS -> "ms";
            case SECONDS -> "s";
            case MINUTES -> "m";
            case HOURS -> "h";
            case DAYS -> "d";
        };
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy