package com.comphenix.protocol.timing; import java.util.ArrayList; import java.util.List; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; /** * Represents an online algortihm of computing histograms over time. * @author Kristian */ public class HistogramStream extends OnlineComputation { /** * Each bin in the histogram, indexed by time. */ protected List bins; /** * The current statistics stream we are updating. */ protected StatisticsStream current; /** * The maximum number of observations in each bin. */ protected int binWidth; /** * The number of total observations. */ protected int count; /** * Construct a new histogram stream which splits up every observation in different bins, ordered by time. * @param binWidth - maximum number of observations in each bin. */ public HistogramStream(int binWidth) { this(new ArrayList(), new StatisticsStream(), binWidth); } /** * Construct a new copy of the given histogram. * @param other - the histogram to copy. */ public HistogramStream(HistogramStream other) { // Deep cloning for (StatisticsStream stream : other.bins) { StatisticsStream copy = stream.copy(); // Update current if (stream == other.current) this.current = copy; this.bins.add(copy); } this.binWidth = other.binWidth; } /** * Construct a new histogram stream. * @param bins - list of bins. * @param current - the current selected bin. This will be added to the list if it is not already present. * @param binWidth - the desired number of observations in each bin. */ protected HistogramStream(List bins, StatisticsStream current, int binWidth) { if (binWidth < 1) throw new IllegalArgumentException("binWidth cannot be less than 1"); this.bins = Preconditions.checkNotNull(bins, "bins cannot be NULL"); this.current = Preconditions.checkNotNull(current, "current cannot be NULL"); this.binWidth = binWidth; if (!this.bins.contains(current)) { this.bins.add(current); } } @Override public HistogramStream copy() { return new HistogramStream(this); } /** * Retrieve an immutable view of every bin in the histogram. * @return Every bin in the histogram. */ public ImmutableList getBins() { return ImmutableList.copyOf(bins); } @Override public void observe(double value) { checkOverflow(); count++; current.observe(value); } /** * See if the current bin has overflowed. If so, construct a new bin and set it as the current. */ protected void checkOverflow() { if (current.getCount() >= binWidth) { bins.add(current = new StatisticsStream()); } } /** * Retrieve the total statistics of every bin in the histogram. *

* This method is not thread safe. * @return The total statistics. */ public StatisticsStream getTotal() { StatisticsStream sum = null; for (StatisticsStream stream : bins) { sum = sum != null ? stream.add(sum) : stream; } return sum; } @Override public int getCount() { return count; } }