co.paralleluniverse.common.benchmark.StripedHistogram Maven / Gradle / Ivy
/*
* Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.
*
* This program and the accompanying materials are dual-licensed under
* either the terms of the Eclipse Public License v1.0 as published by
* the Eclipse Foundation
*
* or (per the licensee's choosing)
*
* under the terms of the GNU Lesser General Public License version 3.0
* as published by the Free Software Foundation.
*/
package co.paralleluniverse.common.benchmark;
import org.HdrHistogram.AbstractHistogram;
import org.HdrHistogram.Histogram;
/**
*
* @author pron
*/
public class StripedHistogram {
private final AbstractHistogram mainHistogram;
private final Striped hs;
private final long highestTrackableValue;
private final int numberOfSignificantValueDigits;
/**
* Construct a Histogram given the Highest value to be tracked and a number of significant decimal digits
*
* @param highestTrackableValue The highest value to be tracked by the histogram. Must be a positive
* integer that is {@code >= 2}.
* @param numberOfSignificantValueDigits The number of significant decimal digits to which the histogram will
* maintain value resolution and separation. Must be a non-negative
* integer between 0 and 5.
*/
public StripedHistogram(long highestTrackableValue, int numberOfSignificantValueDigits) {
this.highestTrackableValue = highestTrackableValue;
this.numberOfSignificantValueDigits = numberOfSignificantValueDigits;
this.mainHistogram = new Histogram(highestTrackableValue, numberOfSignificantValueDigits);
this.hs = new Striped() {
@Override
protected AbstractHistogram newResource() {
return new Histogram(StripedHistogram.this.highestTrackableValue, StripedHistogram.this.numberOfSignificantValueDigits);
}
};
}
public void combine() {
mainHistogram.reset();
for (AbstractHistogram h : hs)
mainHistogram.add(h);
}
private AbstractHistogram get() {
return hs.get();
}
/**
* Record a value in the histogram
*
* @param value The value to be recorded
* @throws ArrayIndexOutOfBoundsException
*/
public void recordValue(long value) throws ArrayIndexOutOfBoundsException {
get().recordValue(value);
}
/**
* Record a value in the histogram (adding to the value's current count)
*
* @param value The value to be recorded
* @param count The number of occurrences of this value to record
* @throws ArrayIndexOutOfBoundsException
*/
public void recordValueWithCount(final long value, final long count) throws ArrayIndexOutOfBoundsException {
get().recordValueWithCount(value, count);
}
/**
* @deprecated
*
* Record a value in the histogram. This deprecated method has identical behavior to
* recordValueWithExpectedInterval()
. It was renamed to avoid ambiguity.
*
* @param value The value to record
* @param expectedIntervalBetweenValueSamples If expectedIntervalBetweenValueSamples is larger than 0, add
* auto-generated value records as appropriate if value is larger
* than expectedIntervalBetweenValueSamples
* @throws ArrayIndexOutOfBoundsException
*/
@Deprecated
public void recordValue(long value, long expectedIntervalBetweenValueSamples) throws ArrayIndexOutOfBoundsException {
get().recordValue(value, expectedIntervalBetweenValueSamples);
}
/**
* Record a value in the histogram.
*
* To compensate for the loss of sampled values when a recorded value is larger than the expected
* interval between value samples, Histogram will auto-generate an additional series of decreasingly-smaller
* (down to the expectedIntervalBetweenValueSamples) value records.
*
* Note: This is a at-recording correction method, as opposed to the post-recording correction method provided
* by {@link #getHistogramDataCorrectedForCoordinatedOmission(long) getHistogramCorrectedForCoordinatedOmission}.
* The two methods are mutually exclusive, and only one of the two should be be used on a given data set to correct
* for the same coordinated omission issue.
*
* See notes in the description of the Histogram calls for an illustration of why this corrective behavior is
* important.
*
* @param value The value to record
* @param expectedIntervalBetweenValueSamples If expectedIntervalBetweenValueSamples is larger than 0, add
* auto-generated value records as appropriate if value is larger
* than expectedIntervalBetweenValueSamples
* @throws ArrayIndexOutOfBoundsException
*/
public void recordValueWithExpectedInterval(final long value, final long expectedIntervalBetweenValueSamples) throws ArrayIndexOutOfBoundsException {
get().recordValueWithExpectedInterval(value, expectedIntervalBetweenValueSamples);
}
/**
* Reset the contents and stats of this histogram
*/
public void reset() {
for (AbstractHistogram h : hs)
h.reset();
mainHistogram.reset();
}
/**
* Provide access to the histogram's data set, corrected for coordinated omission.
*
* Note: This is a post-correction method, as opposed to the at-recording correction method provided
* by {@link #recordValueWithExpectedInterval(long, long) recordValueWithExpectedInterval}. The two
* methods are mutually exclusive, and only one of the two should be be used on a given data set to correct
* for the same coordinated omission issue.
*
* @return a {@code HistogramData} that can be used to query stats and iterate through the default (corrected)
* data set.
*/
public AbstractHistogram getHistogramDataCorrectedForCoordinatedOmission(long expectedIntervalBetweenValueSamples) {
combine();
return mainHistogram.copyCorrectedForCoordinatedOmission(expectedIntervalBetweenValueSamples);
}
/**
* get the configured numberOfSignificantValueDigits
*
* @return numberOfSignificantValueDigits
*/
public int getNumberOfSignificantValueDigits() {
return numberOfSignificantValueDigits;
}
/**
* get the configured highestTrackableValue
*
* @return highestTrackableValue
*/
public long getHighestTrackableValue() {
return highestTrackableValue;
}
/**
* Get the size (in value units) of the range of values that are equivalent to the given value within the
* histogram's resolution. Where "equivalent" means that value samples recorded for any two
* equivalent values are counted in a common total count.
*
* @param value The given value
* @return The lowest value that is equivalent to the given value within the histogram's resolution.
*/
public long sizeOfEquivalentValueRange(long value) {
return mainHistogram.sizeOfEquivalentValueRange(value);
}
/**
* Get the lowest value that is equivalent to the given value within the histogram's resolution.
* Where "equivalent" means that value samples recorded for any two
* equivalent values are counted in a common total count.
*
* @param value The given value
* @return The lowest value that is equivalent to the given value within the histogram's resolution.
*/
public long lowestEquivalentValue(long value) {
return mainHistogram.lowestEquivalentValue(value);
}
/**
* Get the highest value that is equivalent to the given value within the histogram's resolution.
* Where "equivalent" means that value samples recorded for any two
* equivalent values are counted in a common total count.
*
* @param value The given value
* @return The highest value that is equivalent to the given value within the histogram's resolution.
*/
public long highestEquivalentValue(long value) {
return mainHistogram.highestEquivalentValue(value);
}
/**
* Get a value that lies in the middle (rounded up) of the range of values equivalent the given value.
* Where "equivalent" means that value samples recorded for any two
* equivalent values are counted in a common total count.
*
* @param value The given value
* @return The value lies in the middle (rounded up) of the range of values equivalent the given value.
*/
public long medianEquivalentValue(long value) {
return mainHistogram.medianEquivalentValue(value);
}
/**
* Get the next value that is not equivalent to the given value within the histogram's resolution.
* Where "equivalent" means that value samples recorded for any two
* equivalent values are counted in a common total count.
*
* @param value The given value
* @return The next value that is not equivalent to the given value within the histogram's resolution.
*/
public long nextNonEquivalentValue(long value) {
return mainHistogram.nextNonEquivalentValue(value);
}
/**
* Determine if two values are equivalent with the histogram's resolution.
* Where "equivalent" means that value samples recorded for any two
* equivalent values are counted in a common total count.
*
* @param value1 first value to compare
* @param value2 second value to compare
* @return True if values are equivalent with the histogram's resolution.
*/
public boolean valuesAreEquivalent(long value1, long value2) {
return (lowestEquivalentValue(value1) == lowestEquivalentValue(value2));
}
}