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

com.addc.commons.statistcs.collector.Timer Maven / Gradle / Ivy

Go to download

The addc-statistics library supplies classes for collecting statistics including counters, timers and accumulators and exposing these as MBeans.

There is a newer version: 2.6
Show newest version
package com.addc.commons.statistcs.collector;

import java.text.NumberFormat;
import java.util.Locale;

import javax.management.MBeanAttributeInfo;
import javax.management.MBeanInfo;

import com.addc.commons.Constants;
import com.addc.commons.Mutex;
import com.addc.commons.jmx.JmxBeanImpl;

/**
 * The Timer times operations in nano seconds (more or less depending on the OS
 * and hardware). It also counts the number of periods it has timed. When a
 * timer starts it can only be stopped from the same thread.
 */
public class Timer extends JmxBeanImpl implements IMbTimer {
    public static final double MILLI_NANO= Constants.NANOS_PER_MILLI * 1.0d;
    public static final double SEC_NANO= MILLI_NANO * 1000.0d;
    private static final NumberFormat FORMATTER= NumberFormat.getNumberInstance(Locale.getDefault());
    private static final String MS= " ms";
    private final ThreadLocal starttime= new ThreadLocal<>();
    private long firstStart;
    private long lastStop;
    private long totalTime;
    private long timerCounter;
    private long minValue= Long.MAX_VALUE;
    private long maxValue;
    private double totalSquares;
    private final String name;
    private final Mutex lock= new Mutex();

    static {
        FORMATTER.setMaximumFractionDigits(4);
        FORMATTER.setMinimumFractionDigits(1);
        FORMATTER.setMinimumIntegerDigits(1);
    }

    /**
     * Create new Timer
     * 
     * @param name
     *            The unique name for this timer
     */
    public Timer(String name) {
        super(IMbTimer.class);
        this.name= name;
    }

    /**
     * Start timing
     */
    public void start() {
        synchronized (lock) {
            if (starttime.get() == null) {
                long t= System.nanoTime();
                starttime.set(t);
                if (firstStart == 0L) {
                    firstStart= t;
                }
            }
        }
    }

    /**
     * stop timing
     */
    public void stop() {
        synchronized (lock) {
            Long l= starttime.get();
            if (l != null) {
                starttime.set(null);
                lastStop= System.nanoTime();
                long time= lastStop - l;
                totalTime+= time;
                totalSquares+= (time * time);
                maxValue= Math.max(maxValue, time);
                minValue= Math.min(minValue, time);
                timerCounter++;
            }
        }
    }

    @Override
    public String getAverageTimeMillis() {
        synchronized (lock) {
            return FORMATTER.format(getAverageTime()) + MS;
        }
    }

    @Override
    public String getRmsTimeMillis() {
        synchronized (lock) {
            return FORMATTER.format(getRmsTime()) + MS;
        }
    }

    @Override
    public String getMinValueMillis() {
        synchronized (lock) {
            return FORMATTER.format(getMinValue()) + MS;
        }
    }

    @Override
    public String getMaxValueMillis() {
        synchronized (lock) {
            return FORMATTER.format(getMaxValue()) + MS;
        }
    }

    @Override
    public String getThroughput() {
        synchronized (lock) {
            return FORMATTER.format(getEventsPerSecond()) + " per second";
        }
    }

    @Override
    public long getEventCount() {
        long ret;
        synchronized (lock) {
            ret= timerCounter;
        }
        return ret;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public String getStandardDeviation() {
        synchronized (lock) {
            return FORMATTER.format(calcSigma()) + MS;
        }
    }

    @Override
    protected String getDescription(MBeanInfo info) {
        return "Collects timing statistics on sections of code";
    }

    @Override
    protected String getDescription(MBeanAttributeInfo info) {
        if ("AverageTimeMillis".equals(info.getName())) {
            return "The arithmetical average of the times in milliseconds";
        }
        if ("RmsTimeMillis".equals(info.getName())) {
            return "The RMS average of the times in milliseconds";
        }
        if ("MinValueMillis".equals(info.getName())) {
            return "The minimum value timed in milliseconds";
        }
        if ("MaxValueMillis".equals(info.getName())) {
            return "The maximum value timed in milliseconds";
        }
        if ("EventCount".equals(info.getName())) {
            return "The number events that were timed";
        }
        if ("Throughput".equals(info.getName())) {
            return "The throughput in events/sec";
        }
        if ("StandardDeviation".equals(info.getName())) {
            return "The standard deviation for the current data set";
        }
        if ("Name".equals(info.getName())) {
            return "The name of this Timer";
        }

        return super.getDescription(info);
    }

    /**
     * Get the standard deviation for the times
     *
     * @return the standard deviation for the times
     */
    public double calcSigma() {
        double ret;
        synchronized (lock) {
            if (timerCounter == 0) {
                ret= 0.0d;
            } else {
                double div= (timerCounter - 1.0d);
                ret= (totalSquares / div) - Math.pow((totalTime / div), 2.0d);
            }
        }
        return ret;
    }

    /**
     * Get the arithmetic average time for the operation
     *
     * @return the arithmetic average time for the operation
     */
    public double getAverageTime() {
        double ret;
        synchronized (lock) {
            if (timerCounter == 0) {
                ret= 0.0d;
            } else {
                ret= (((double) totalTime / (double) timerCounter) / MILLI_NANO);
            }
        }
        return ret;
    }

    /**
     * Get the algebraic average time for the operation
     *
     * @return the algebraic average time for the operation
     */
    public double getRmsTime() {
        double ret;
        synchronized (lock) {
            if (timerCounter == 0) {
                ret= 0.0d;
            } else {
                ret= Math.sqrt((totalSquares / timerCounter)) / MILLI_NANO;
            }
        }
        return ret;
    }

    /**
     * Get the minimum value r4ecorde
     *
     * @return the minimum value r4ecorde
     */
    public double getMinValue() {
        double ret;
        synchronized (lock) {
            ret= (minValue / MILLI_NANO);
        }
        return ret;
    }

    /**
     * Get the maximum value r4ecorde
     *
     * @return the maximum value r4ecorde
     */
    public double getMaxValue() {
        double ret;
        synchronized (lock) {
            ret= (maxValue / MILLI_NANO);
        }
        return ret;
    }

    /**
     * Get the number of events recorded per second
     *
     * @return the number of events recorded per second
     */
    public double getEventsPerSecond() {
        double ret;
        synchronized (lock) {
            double period= totalTime / SEC_NANO;
            ret= (timerCounter / period);
        }
        return ret;
    }

    /**
     * Clear and reset the timer
     */
    public void clear() {
        synchronized (lock) {
            totalTime= 0L;
            timerCounter= 0L;
            totalSquares= 0.0d;
            firstStart= 0L;
            lastStop= 0L;
            minValue= Long.MAX_VALUE;
            maxValue= 0L;
            starttime.set(null);
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy