#pragma once #include #include #include struct hdr_histogram; namespace NHdr { /** * A High Dynamic Range (HDR) Histogram * * THdrHistogram 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. */ class THistogram: public TMoveOnly { public: /** * Construct a histogram 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. Default * allocator will be used to allocate underlying memory. * * @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. */ THistogram(i64 highestTrackableValue, i32 numberOfSignificantValueDigits) : THistogram(1, highestTrackableValue, numberOfSignificantValueDigits) { } /** * Construct a histogram given the Lowest and Highest values to be tracked * and a number of significant decimal digits. Providing a * lowestDiscernibleValue is useful in 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 discerned * (distinguished from 0) by the histogram. Must be a positive * integer that is >= 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 * >= (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. * * @param allocator Specifies allocator which will be used to allocate * memory for histogram. */ THistogram(i64 lowestDiscernibleValue, i64 highestTrackableValue, i32 numberOfSignificantValueDigits, IAllocator* allocator = TDefaultAllocator::Instance()); ~THistogram(); // Histogram structure querying support ----------------------------------- /** * @return The configured lowestDiscernibleValue */ i64 GetLowestDiscernibleValue() const; /** * @return The configured highestTrackableValue */ i64 GetHighestTrackableValue() const; /** * @return The configured numberOfSignificantValueDigits */ i32 GetNumberOfSignificantValueDigits() const; /** * @return The size of allocated memory for histogram */ size_t GetMemorySize() const; /** * @return The number of created counters */ i32 GetCountsLen() const; /** * @return The total count of all recorded values in the histogram */ i64 GetTotalCount() const; // Value recording support ------------------------------------------------ /** * Records a value in the histogram, will round this value of to a * precision at or better than the NumberOfSignificantValueDigits specified * at construction time. * * @param value Value to add to the histogram * @return false if the value is larger than the HighestTrackableValue * and can't be recorded, true otherwise. */ bool RecordValue(i64 value); /** * Records count values in the histogram, will round this value of to a * precision at or better than the NumberOfSignificantValueDigits specified * at construction time. * * @param value Value to add to the histogram * @param count Number of values to add to the histogram * @return false if the value is larger than the HighestTrackableValue * and can't be recorded, true otherwise. */ bool RecordValues(i64 value, i64 count); /** * Records a value in the histogram and backfill based on an expected * interval. Value will be rounded this to a precision at or better * than the NumberOfSignificantValueDigits specified at contruction time. * This is specifically used for recording latency. If the value is larger * than the expectedInterval then the latency recording system has * experienced co-ordinated omission. This method fills in the values that * would have occured had the client providing the load not been blocked. * * @param value Value to add to the histogram * @param expectedInterval The delay between recording values * @return false if the value is larger than the HighestTrackableValue * and can't be recorded, true otherwise. */ bool RecordValueWithExpectedInterval(i64 value, i64 expectedInterval); /** * Record a value in the histogram count times. Applies the same correcting * logic as {@link THistogram::RecordValueWithExpectedInterval}. * * @param value Value to add to the histogram * @param count Number of values to add to the histogram * @param expectedInterval The delay between recording values. * @return false if the value is larger than the HighestTrackableValue * and can't be recorded, true otherwise. */ bool RecordValuesWithExpectedInterval( i64 value, i64 count, i64 expectedInterval); /** * Adds all of the values from rhs to this histogram. Will return the * number of values that are dropped when copying. Values will be dropped * if they around outside of [LowestDiscernibleValue, GetHighestTrackableValue]. * * @param rhs Histogram to copy values from. * @return The number of values dropped when copying. */ i64 Add(const THistogram& rhs); /** * Adds all of the values from rhs to this histogram. Will return the * number of values that are dropped when copying. Values will be dropped * if they around outside of [LowestDiscernibleValue, GetHighestTrackableValue]. * Applies the same correcting logic as * {@link THistogram::RecordValueWithExpectedInterval}. * * @param rhs Histogram to copy values from. * @return The number of values dropped when copying. */ i64 AddWithExpectedInterval(const THistogram& rhs, i64 expectedInterval); // Histogram Data access support ------------------------------------------ /** * Get the lowest recorded value level in the histogram. If the histogram * has no recorded values, the value returned is undefined. * * @return the Min value recorded in the histogram */ i64 GetMin() const; /** * Get the highest recorded value level in the histogram. If the histogram * has no recorded values, the value returned is undefined. * * @return the Max value recorded in the histogram */ i64 GetMax() const; /** * Get the computed mean value of all recorded values in the histogram * * @return the mean value (in value units) of the histogram data */ double GetMean() const; /** * Get the computed standard deviation of all recorded values in the histogram * * @return the standard deviation (in value units) of the histogram data */ double GetStdDeviation() const; /** * Get the value at a given percentile. * Note that two values are "equivalent" in this statement if * {@link THistogram::ValuesAreEquivalent} would return true. * * @param percentile The percentile for which to return the associated * value * @return The value that the given percentage of the overall recorded * value entries in the histogram are either smaller than or * equivalent to. When the percentile is 0.0, returns the value * that all value entries in the histogram are either larger than * or equivalent to. */ i64 GetValueAtPercentile(double percentile) const; /** * Get the count of recorded values at a specific value (to within the * histogram resolution at the value level). * * @param value The value for which to provide the recorded count * @return The total count of values recorded in the histogram within the * value range that is >= GetLowestEquivalentValue(value) and * <= GetHighestEquivalentValue(value) */ i64 GetCountAtValue(i64 value) const; /** * 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 v1 first value to compare * @param v2 second value to compare * @return True if values are equivalent with the histogram's resolution. */ bool ValuesAreEqual(i64 v1, i64 v2) const; /** * 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. */ i64 GetLowestEquivalentValue(i64 value) const; /** * 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. */ i64 GetHighestEquivalentValue(i64 value) const; /** * 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. */ i64 GetMedianEquivalentValue(i64 value) const; // misc functions --------------------------------------------------------- /** * Reset a histogram to zero - empty out a histogram and re-initialise it. * If you want to re-use an existing histogram, but reset everything back * to zero, this is the routine to use. */ void Reset(); const hdr_histogram* GetHdrHistogramImpl() const { return Data_.Get(); } private: THolder Data_; IAllocator* Allocator_; }; }