High Dynamic Range (HDR) Histogram for recording and analyzing value distributions with configurable precision across wide dynamic ranges.
—
Core histogram functionality for recording integer values and performing basic statistical analysis. These classes provide the foundation for all HdrHistogram operations.
The abstract base class providing core histogram functionality.
public abstract class AbstractHistogram
extends AbstractHistogramBase
implements EncodableHistogram, ValueRecorder, Serializable {
// Constructors
protected AbstractHistogram(int numberOfSignificantValueDigits);
protected AbstractHistogram(long lowestDiscernibleValue,
long highestTrackableValue,
int numberOfSignificantValueDigits);
protected AbstractHistogram(AbstractHistogram source);
}// Basic recording methods
void recordValue(long value);
void recordValueWithCount(long value, long count);
void recordValueWithExpectedInterval(long value, long expectedInterval);
void recordConvertedDoubleValueWithCount(double value, long count);Usage Examples:
// Record individual values
histogram.recordValue(1234); // Single measurement
histogram.recordValueWithCount(5678, 10); // Value occurred 10 times
// Record double values (automatically converted to integer representation)
histogram.recordConvertedDoubleValueWithCount(12.34, 5); // Convert 12.34 to int
// Coordinated omission correction
// If expecting measurements every 100ms, but got 1500ms due to pause
histogram.recordValueWithExpectedInterval(1500, 100);// Count and basic statistics
long getTotalCount();
long getMaxValue();
double getMaxValueAsDouble();
long getMinValue();
long getMinNonZeroValue();
double getMean();
double getStdDeviation();
// Percentile queries
long getValueAtPercentile(double percentile);
double getPercentileAtOrBelowValue(long value);
// Value-specific queries
long getCountAtValue(long value);
long getCountBetweenValues(long lowValue, long highValue);Usage Examples:
// Basic statistics
long totalSamples = histogram.getTotalCount();
double averageLatency = histogram.getMean();
long maxLatency = histogram.getMaxValue();
// Percentile analysis
long p50 = histogram.getValueAtPercentile(50.0); // Median
long p95 = histogram.getValueAtPercentile(95.0); // 95th percentile
long p99 = histogram.getValueAtPercentile(99.0); // 99th percentile
long p999 = histogram.getValueAtPercentile(99.9); // 99.9th percentile
// Value analysis
long countAt1000 = histogram.getCountAtValue(1000);
long countBelow2000 = histogram.getCountBetweenValues(0, 2000);
double percentileOf1500 = histogram.getPercentileAtOrBelowValue(1500);// Configuration queries
long getLowestDiscernibleValue();
long getHighestTrackableValue();
int getNumberOfSignificantValueDigits();
int getEstimatedFootprintInBytes();
// Auto-resize support
void setAutoResize(boolean autoResize);
boolean isAutoResize();
boolean supportsAutoResize();
// Timestamp and tagging
long getStartTimeStamp();
void setStartTimeStamp(long timestamp);
long getEndTimeStamp();
void setEndTimeStamp(long timestamp);
String getTag();
void setTag(String tag);// Histogram manipulation
void reset();
void add(AbstractHistogram other);
void subtract(AbstractHistogram other);
abstract AbstractHistogram copy();
abstract AbstractHistogram copyCorrectedForCoordinatedOmission(long expectedInterval);
// Coordinated omission correction operations
void addWhileCorrectingForCoordinatedOmission(AbstractHistogram otherHistogram,
long expectedIntervalBetweenValueSamples);
void copyInto(AbstractHistogram targetHistogram);
void copyIntoCorrectedForCoordinatedOmission(AbstractHistogram targetHistogram,
long expectedIntervalBetweenValueSamples);
// Value shifting (multiply/divide by powers of 2)
void shiftValuesLeft(int numberOfBinaryOrdersOfMagnitude);
void shiftValuesRight(int numberOfBinaryOrdersOfMagnitude);
// Comparison operations
boolean equals(Object other);
int hashCode();
String toString();Usage Examples:
// Combine histograms
AbstractHistogram combined = histogram1.copy();
combined.add(histogram2); // Add histogram2's data to combined
// Coordinated omission correction
AbstractHistogram corrected = histogram.copyCorrectedForCoordinatedOmission(100);
// Add another histogram with coordinated omission correction
combined.addWhileCorrectingForCoordinatedOmission(histogram3, 100);
// Copy into existing histogram (reuse target histogram instance)
AbstractHistogram target = new Histogram(3);
histogram.copyInto(target); // Copy histogram data into target
// Copy with coordinated omission correction into existing histogram
histogram.copyIntoCorrectedForCoordinatedOmission(target, 100);
// Scale values (multiply by 2^3 = 8)
histogram.shiftValuesLeft(3);
// Object methods
String description = histogram.toString(); // String representation
boolean same = histogram1.equals(histogram2); // Compare histograms
int hash = histogram.hashCode(); // Hash code for collections
// Reset for reuse
histogram.reset();// Value equivalence methods
long sizeOfEquivalentValueRange(long value);
long lowestEquivalentValue(long value);
long highestEquivalentValue(long value);
long medianEquivalentValue(long value);
long nextNonEquivalentValue(long value);
boolean valuesAreEquivalent(long value1, long value2);Usage Examples:
// Understand histogram precision
long value = 1000;
long rangeSize = histogram.sizeOfEquivalentValueRange(value);
long lowest = histogram.lowestEquivalentValue(value);
long highest = histogram.highestEquivalentValue(value);
System.out.println("Value " + value + " represents range [" + lowest + ", " + highest + "]");
System.out.println("Range size: " + rangeSize);// Iterator factory methods for data analysis
Percentiles percentiles(int percentileTicksPerHalfDistance);
LinearBucketValues linearBucketValues(long valueUnitsPerBucket);
LogarithmicBucketValues logarithmicBucketValues(long valueUnitsInFirstBucket, double logBase);
RecordedValues recordedValues();
AllValues allValues();Usage Examples:
// Create different iterators for data analysis
Percentiles percentiles = histogram.percentiles(5); // 5 ticks per half distance
LinearBucketValues linear = histogram.linearBucketValues(1000); // 1000 unit buckets
LogarithmicBucketValues log = histogram.logarithmicBucketValues(1000, 2.0); // Base 2
RecordedValues recorded = histogram.recordedValues(); // Only recorded values
AllValues all = histogram.allValues(); // All possible values
// Use iterators in for-each loops
for (HistogramIterationValue value : percentiles) {
System.out.printf("Percentile: %.2f%%, Value: %d%n",
value.getPercentile(), value.getValueIteratedTo());
}The standard concrete implementation of AbstractHistogram.
public class Histogram extends AbstractHistogram {
// Constructors
public Histogram(int numberOfSignificantValueDigits);
public Histogram(long highestTrackableValue, int numberOfSignificantValueDigits);
public Histogram(long lowestDiscernibleValue,
long highestTrackableValue,
int numberOfSignificantValueDigits);
public Histogram(AbstractHistogram source);
// Factory methods for deserialization
static Histogram decodeFromByteBuffer(ByteBuffer buffer,
long minBarForHighestTrackableValue);
static Histogram decodeFromCompressedByteBuffer(ByteBuffer buffer,
long minBarForHighestTrackableValue);
static Histogram fromString(String base64CompressedHistogramString);
// Implementation methods
public Histogram copy();
public Histogram copyCorrectedForCoordinatedOmission(long expectedInterval);
}Usage Examples:
// Create different histogram configurations
Histogram autoResize = new Histogram(3); // Auto-resizing, 3 significant digits
Histogram fixedRange = new Histogram(1_000_000, 3); // Max value 1M, 3 digits
Histogram fullSpec = new Histogram(1, 1_000_000, 3); // Min 1, max 1M, 3 digits
// Copy constructors
Histogram copy = new Histogram(original);
Histogram corrected = original.copyCorrectedForCoordinatedOmission(1000);
// Deserialization
byte[] data = getHistogramData();
ByteBuffer buffer = ByteBuffer.wrap(data);
Histogram restored = Histogram.decodeFromByteBuffer(buffer, 2);Core interface for value recording functionality.
public interface ValueRecorder {
void recordValue(long value) throws ArrayIndexOutOfBoundsException;
void recordValueWithCount(long value, long count) throws ArrayIndexOutOfBoundsException;
void recordValueWithExpectedInterval(long value, long expectedInterval)
throws ArrayIndexOutOfBoundsException;
void reset();
}// Encoding methods for data persistence
int getNeededByteBufferCapacity();
int encodeIntoByteBuffer(ByteBuffer buffer);
int encodeIntoCompressedByteBuffer(ByteBuffer targetBuffer, int compressionLevel);
int encodeIntoCompressedByteBuffer(ByteBuffer targetBuffer);Usage Examples:
// Encode histogram to byte buffer for storage/transmission
ByteBuffer buffer = ByteBuffer.allocate(histogram.getNeededByteBufferCapacity());
int bytesWritten = histogram.encodeIntoByteBuffer(buffer);
// Encode with compression
ByteBuffer compressedBuffer = ByteBuffer.allocate(histogram.getNeededByteBufferCapacity());
int compressedBytes = histogram.encodeIntoCompressedByteBuffer(compressedBuffer, 9);
// Default compression level
int defaultCompressed = histogram.encodeIntoCompressedByteBuffer(compressedBuffer);// Output methods
void outputPercentileDistribution(PrintStream printStream,
Double outputValueUnitScalingRatio);
void outputPercentileDistribution(PrintStream printStream,
int percentileTicksPerHalfDistance,
Double outputValueUnitScalingRatio);
void outputPercentileDistribution(PrintStream printStream,
int percentileTicksPerHalfDistance,
Double outputValueUnitScalingRatio,
boolean useCsvFormat);Usage Examples:
// Output percentile distribution to console
histogram.outputPercentileDistribution(System.out, 1000.0); // Scale to milliseconds
// Output to file with CSV format
try (PrintStream out = new PrintStream(new FileOutputStream("latencies.csv"))) {
histogram.outputPercentileDistribution(out, 5, 1000.0, true);
}Example Configurations:
// Latency measurement (microseconds): expect 1μs to 1 second
Histogram latency = new Histogram(1, 1_000_000, 3);
// Throughput measurement (operations/second): auto-resize
Histogram throughput = new Histogram(3);
// High precision latency (nanoseconds): 1ns to 10 seconds
Histogram preciseLatency = new Histogram(1, 10_000_000_000L, 4);Histogram class is NOT thread-safe. For concurrent access:
ConcurrentHistogramRecorder for producer-consumer scenariosMemory usage depends on:
Estimate memory usage with getEstimatedFootprintInBytes() method.
Install with Tessl CLI
npx tessl i tessl/maven-org-hdrhistogram--hdr-histogram