ProtocolLib/src/main/java/com/comphenix/protocol/timing/HistogramStream.java

126 lines
3.5 KiB
Java

package com.comphenix.protocol.timing;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.List;
/**
* 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<StatisticsStream> 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<StatisticsStream> 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<StatisticsStream> 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.
* <p>
* 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;
}
}