All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.HdrHistogram.PackedHistogram Maven / Gradle / Ivy

Go to download

HdrHistogram supports the recording and analyzing sampled data value counts across a configurable integer value range with configurable value precision within the range. Value precision is expressed as the number of significant digits in the value recording, and provides control over value quantization behavior across the value range and the subsequent value resolution at any given level.

There is a newer version: 2.2.2
Show newest version
/**
 * Written by Gil Tene of Azul Systems, and released to the public domain,
 * as explained at http://creativecommons.org/publicdomain/zero/1.0/
 *
 * @author Gil Tene
 */

package org.HdrHistogram;

import org.HdrHistogram.packedarray.PackedLongArray;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.nio.ByteBuffer;
import java.util.zip.DataFormatException;

/**
 * 

A High Dynamic Range (HDR) Histogram that uses a packed internal representation

*

* {@link PackedHistogram} supports the recording and analyzing sampled data value counts across a configurable * integer value range with configurable value precision within the range. Value precision is expressed as the * number of significant digits in the value recording, and provides control over value quantization behavior * across the value range and the subsequent value resolution at any given level. *

* {@link PackedHistogram} tracks value counts in a packed internal representation optimized * for typical histogram recoded values are sparse in the value range and tend to be incremented in small unit counts. * This packed representation tends to require significantly smaller amounts of storage when compared to unpacked * representations, but can incur additional recording cost due to resizing and repacking operations that may * occur as previously unrecorded values are encountered. *

* For example, a {@link PackedHistogram} could be configured to track the counts of observed integer values between 0 and * 3,600,000,000,000 while maintaining a value precision of 3 significant digits across that range. Value quantization * within the range will thus be no larger than 1/1,000th (or 0.1%) of any value. This example Histogram could * be used to track and analyze the counts of observed response times ranging between 1 nanosecond and 1 hour * in magnitude, while maintaining a value resolution of 1 microsecond up to 1 millisecond, a resolution of * 1 millisecond (or better) up to one second, and a resolution of 1 second (or better) up to 1,000 seconds. At its * maximum tracked value (1 hour), it would still maintain a resolution of 3.6 seconds (or better). *

* Auto-resizing: When constructed with no specified value range range (or when auto-resize is turned on with {@link * Histogram#setAutoResize}) a {@link PackedHistogram} will auto-resize its dynamic range to include recorded values as * they are encountered. Note that recording calls that cause auto-resizing may take longer to execute, as resizing * incurs allocation and copying of internal data structures. *

* See package description for {@link org.HdrHistogram} for details. */ public class PackedHistogram extends Histogram { private PackedLongArray packedCounts; @Override long getCountAtIndex(final int index) { return getCountAtNormalizedIndex(normalizeIndex(index, normalizingIndexOffset, countsArrayLength)); } @Override long getCountAtNormalizedIndex(final int index) { long count = packedCounts.get(index); return count; } @Override void incrementCountAtIndex(final int index) { packedCounts.increment(normalizeIndex(index, normalizingIndexOffset, countsArrayLength)); } @Override void addToCountAtIndex(final int index, final long value) { packedCounts.add(normalizeIndex(index, normalizingIndexOffset, countsArrayLength), value); } @Override void setCountAtIndex(int index, long value) { setCountAtNormalizedIndex(normalizeIndex(index, normalizingIndexOffset, countsArrayLength), value); } @Override void setCountAtNormalizedIndex(int index, long value) { packedCounts.set(index, value); } @Override void clearCounts() { packedCounts.clear(); packedCounts.setVirtualLength(countsArrayLength); totalCount = 0; } @Override public PackedHistogram copy() { PackedHistogram copy = new PackedHistogram(this); copy.add(this); return copy; } @Override public PackedHistogram copyCorrectedForCoordinatedOmission(final long expectedIntervalBetweenValueSamples) { PackedHistogram toHistogram = new PackedHistogram(this); toHistogram.addWhileCorrectingForCoordinatedOmission(this, expectedIntervalBetweenValueSamples); return toHistogram; } @Override void resize(long newHighestTrackableValue) { int oldNormalizedZeroIndex = normalizeIndex(0, normalizingIndexOffset, countsArrayLength); int oldCountsArrayLength = countsArrayLength; establishSize(newHighestTrackableValue); if (oldNormalizedZeroIndex != 0) { // We need to shift the stuff from the zero index and up to the end of the array: // When things are shifted in a packed array its not simple to identify the region shifted, // so re-record everything from the old normalized indexes to the new normalized indexes: PackedLongArray newPackedCounts = new PackedLongArray(countsArrayLength, packedCounts.getPhysicalLength()); // Copy everything up to the oldNormalizedZeroIndex in place: for (int fromIndex = 0; fromIndex < oldNormalizedZeroIndex; fromIndex++) { long value = packedCounts.get(fromIndex); if (value != 0) { newPackedCounts.set(fromIndex, value); } } // Copy everything from the oldNormalizedZeroIndex to the end with an index delta shift: int countsDelta = countsArrayLength - oldCountsArrayLength; for (int fromIndex = oldNormalizedZeroIndex; fromIndex < oldCountsArrayLength; fromIndex++) { long value = packedCounts.get(fromIndex); if (value != 0) { int toIndex = fromIndex + countsDelta; newPackedCounts.set(toIndex, value); } } // All unrecorded values are implicitly zero in the packed array packedCounts = newPackedCounts; } else { packedCounts.setVirtualLength(countsArrayLength); } } @Override int _getEstimatedFootprintInBytes() { return 192 + (8 * packedCounts.getPhysicalLength()); } /** * Construct an auto-resizing PackedHistogram with a lowest discernible value of 1 and an auto-adjusting * highestTrackableValue. Can auto-resize up to track values up to (Long.MAX_VALUE / 2). * * @param numberOfSignificantValueDigits Specifies the precision to use. This is 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 PackedHistogram(final int numberOfSignificantValueDigits) { this(1, 2, numberOfSignificantValueDigits); setAutoResize(true); } /** * Construct a PackedHistogram given the Highest value to be tracked and a number of significant decimal digits. The * histogram will be constructed to implicitly track (distinguish from 0) values as low as 1. * * @param highestTrackableValue The highest value to be tracked by the histogram. Must be a positive * integer that is {@literal >=} 2. * @param numberOfSignificantValueDigits Specifies the precision to use. This is 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 PackedHistogram(final long highestTrackableValue, final int numberOfSignificantValueDigits) { this(1, highestTrackableValue, numberOfSignificantValueDigits); } /** * Construct a PackedHistogram given the Lowest and Highest values to be tracked and a number of significant * decimal digits. Providing a lowestDiscernibleValue is useful is situations where the units used * for the histogram's values are much smaller that the minimal accuracy required. E.g. when tracking * time values stated in nanosecond units, where the minimal accuracy required is a microsecond, the * proper value for lowestDiscernibleValue would be 1000. * * @param lowestDiscernibleValue The lowest value that can be tracked (distinguished from 0) by the histogram. * Must be a positive integer that is {@literal >=} 1. May be internally rounded * down to nearest power of 2. * @param highestTrackableValue The highest value to be tracked by the histogram. Must be a positive * integer that is {@literal >=} (2 * lowestDiscernibleValue). * @param numberOfSignificantValueDigits Specifies the precision to use. This is 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 PackedHistogram(final long lowestDiscernibleValue, final long highestTrackableValue, final int numberOfSignificantValueDigits) { super(lowestDiscernibleValue, highestTrackableValue, numberOfSignificantValueDigits, false); packedCounts = new PackedLongArray(countsArrayLength); wordSizeInBytes = 8; } /** * Construct a PackedHistogram with the same range settings as a given source histogram, * duplicating the source's start/end timestamps (but NOT it's contents) * @param source The source histogram to duplicate */ public PackedHistogram(final AbstractHistogram source) { super(source, false); packedCounts = new PackedLongArray(countsArrayLength); wordSizeInBytes = 8; } /** * Construct a new histogram by decoding it from a ByteBuffer. * @param buffer The buffer to decode from * @param minBarForHighestTrackableValue Force highestTrackableValue to be set at least this high * @return The newly constructed histogram */ public static PackedHistogram decodeFromByteBuffer(final ByteBuffer buffer, final long minBarForHighestTrackableValue) { return (PackedHistogram) decodeFromByteBuffer(buffer, PackedHistogram.class, minBarForHighestTrackableValue); } /** * Construct a new histogram by decoding it from a compressed form in a ByteBuffer. * @param buffer The buffer to decode from * @param minBarForHighestTrackableValue Force highestTrackableValue to be set at least this high * @return The newly constructed histogram * @throws DataFormatException on error parsing/decompressing the buffer */ public static PackedHistogram decodeFromCompressedByteBuffer(final ByteBuffer buffer, final long minBarForHighestTrackableValue) throws DataFormatException { return decodeFromCompressedByteBuffer(buffer, PackedHistogram.class, minBarForHighestTrackableValue); } private void readObject(final ObjectInputStream o) throws IOException, ClassNotFoundException { o.defaultReadObject(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy