001package org.javasimon.callback.timeline;
002
003import org.javasimon.utils.SimonUtils;
004
005/**
006 * Stopwatch statistics gathered for a specific time range.
007 * This class is not intended to be thread safe.
008 *
009 * @author gerald
010 */
011public class StopwatchTimeRange extends TimeRange {
012
013        /** Last value. */
014        private long last;
015
016        /** Minimum value. */
017        private long min = Long.MAX_VALUE;
018
019        /** Maximum value. */
020        private long max = Long.MIN_VALUE;
021
022        /** Total sum of all values. */
023        private long total;
024
025        /** Sum of squares. */
026        private long squareTotal;
027
028        /** Counter - number of values. */
029        private long counter;
030
031        /** Main constructor. */
032        public StopwatchTimeRange(long startTimestamp, long endTimestamp) {
033                super(startTimestamp, endTimestamp);
034        }
035
036        /**
037         * Add stopwatch split information.
038         *
039         * @param timestampInMs when the split started, expressed in milliseconds
040         * @param durationInNs how long the split was, expressed in nanoseconds
041         */
042        public void addSplit(long timestampInMs, long durationInNs) {
043                last = durationInNs;
044                total += durationInNs;
045                squareTotal += durationInNs * durationInNs;
046                if (durationInNs > max) {
047                        max = durationInNs;
048                }
049                if (durationInNs < min) {
050                        min = durationInNs;
051                }
052                counter++;
053                lastTimestamp = timestampInMs;
054        }
055
056        public long getLast() {
057                return last;
058        }
059
060        public long getMin() {
061                return min;
062        }
063
064        public long getMax() {
065                return max;
066        }
067
068        public long getTotal() {
069                return total;
070        }
071
072        public long getCounter() {
073                return counter;
074        }
075
076        /** Computes mean (average) using total and non-zero counter. */
077        private double computeMean() {
078                return ((double) total) / counter;
079        }
080
081        /**
082         * Compute mean (average) duration.
083         *
084         * @return mean (average) duration.
085         */
086        public Double getMean() {
087                return counter == 0 ? Double.NaN : computeMean();
088        }
089
090        /**
091         * Compute variance.
092         *
093         * @return variance
094         */
095        public Double getVariance() {
096                if (counter == 0) {
097                        return Double.NaN;
098                } else {
099                        final double mean = computeMean();
100                        final double meanSquare = mean * mean;
101                        final double squareMean = ((double) squareTotal) / counter;
102                        return squareMean - meanSquare;
103                }
104        }
105
106        /**
107         * Computes standard deviation.
108         *
109         * @return standard deviation
110         */
111        public Double getStandardDeviation() {
112                return Math.sqrt(getVariance());
113        }
114
115        @Override
116        protected StringBuilder toStringBuilder(StringBuilder stringBuilder) {
117                return super.toStringBuilder(stringBuilder)
118                        .append(" counter=").append(counter)
119                        .append(" total=").append(SimonUtils.presentNanoTime(total))
120                        .append(" min=").append(SimonUtils.presentNanoTime(min))
121                        .append(" mean=").append(SimonUtils.presentNanoTime(getMean()))
122                        .append(" last=").append(SimonUtils.presentNanoTime(getLast()))
123                        .append(" max=").append(SimonUtils.presentNanoTime(max))
124                        .append(" stddev=").append(SimonUtils.presentNanoTime(getStandardDeviation()));
125        }
126}