예제 #1
0
 /// <summary>
 /// Add the contents of another histogram to this one.
 /// </summary>
 /// <param name="fromHistogram">The other histogram.</param>
 /// <exception cref="System.IndexOutOfRangeException">if values in fromHistogram's are higher than highestTrackableValue.</exception>
 public virtual void Add(HistogramBase fromHistogram)
 {
     if (HighestTrackableValue < fromHistogram.HighestTrackableValue)
     {
         throw new ArgumentOutOfRangeException(nameof(fromHistogram), $"The other histogram covers a wider range ({fromHistogram.HighestTrackableValue} than this one ({HighestTrackableValue}).");
     }
     if ((BucketCount == fromHistogram.BucketCount) &&
         (SubBucketCount == fromHistogram.SubBucketCount) &&
         (_unitMagnitude == fromHistogram._unitMagnitude))
     {
         // Counts arrays are of the same length and meaning, so we can just iterate and add directly:
         for (var i = 0; i < fromHistogram.CountsArrayLength; i++)
         {
             AddToCountAtIndex(i, fromHistogram.GetCountAtIndex(i));
         }
     }
     else
     {
         // Arrays are not a direct match, so we can't just stream through and add them.
         // Instead, go through the array and add each non-zero value found at it's proper value:
         for (var i = 0; i < fromHistogram.CountsArrayLength; i++)
         {
             var count = fromHistogram.GetCountAtIndex(i);
             RecordValueWithCount(fromHistogram.ValueFromIndex(i), count);
         }
     }
 }
예제 #2
0
 /// <summary>
 /// Copy this histogram into the target histogram, overwriting it's contents.
 /// </summary>
 /// <param name="source">The source histogram</param>
 /// <param name="targetHistogram">the histogram to copy into</param>
 public static void CopyInto(this HistogramBase source, HistogramBase targetHistogram)
 {
     targetHistogram.Reset();
     targetHistogram.Add(source);
     targetHistogram.StartTimeStamp = source.StartTimeStamp;
     targetHistogram.EndTimeStamp   = source.EndTimeStamp;
 }
예제 #3
0
 private void ValidateFitAsReplacementHistogram(HistogramBase replacementHistogram)
 {
     if (replacementHistogram != null && replacementHistogram.InstanceId != _activeHistogram.InstanceId)
     {
         throw new InvalidOperationException(
                   $"Replacement histogram must have been obtained via a previous getIntervalHistogram() call from this {GetType().Name} instance");
     }
 }
예제 #4
0
 /// <summary>
 /// Place a copy of the value counts accumulated since accumulated (since the last interval histogram was taken) into <paramref name="targetHistogram"/>.
 /// This will overwrite the existing data in <paramref name="targetHistogram"/>.
 /// Calling <see cref="GetIntervalHistogramInto(HistogramBase)"/> will reset the value counts, and start accumulating value counts for the next interval.
 /// </summary>
 /// <param name="targetHistogram">The histogram into which the interval histogram's data should be copied.</param>
 public void GetIntervalHistogramInto(HistogramBase targetHistogram)
 {
     lock (_gate)
     {
         PerformIntervalSample();
         _inactiveHistogram.CopyInto(targetHistogram);
     }
 }
예제 #5
0
 /// <summary>
 /// Creates a recorder that will delegate recording to histograms created from these parameters.
 /// </summary>
 /// <param name="lowestDiscernibleValue">The lowest value that can be tracked (distinguished from 0) by the histogram.
 /// Must be a positive integer that is &gt;= 1.
 /// May be internally rounded down to nearest power of 2.
 /// </param>
 /// <param name="highestTrackableValue">The highest value to be tracked by the histogram.
 /// Must be a positive integer that is &gt;= (2 * lowestTrackableValue).
 /// </param>
 /// <param name="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.
 /// </param>
 /// <param name="histogramFactory">The factory to be used to actually create instances of <seealso cref="HistogramBase"/>.</param>
 public Recorder(
     long lowestDiscernibleValue,
     long highestTrackableValue,
     int numberOfSignificantValueDigits,
     HistogramFactoryDelegate histogramFactory)
 {
     _histogramFactory  = histogramFactory;
     _activeHistogram   = histogramFactory(_instanceId, lowestDiscernibleValue, highestTrackableValue, numberOfSignificantValueDigits);
     _inactiveHistogram = histogramFactory(_instanceId, lowestDiscernibleValue, highestTrackableValue, numberOfSignificantValueDigits);
     _activeHistogram.StartTimeStamp = DateTime.Now.MillisecondsSinceUnixEpoch();
 }
예제 #6
0
        /// <summary>
        /// Get the computed mean value of all recorded values in the histogram
        /// </summary>
        /// <returns>the mean value (in value units) of the histogram data</returns>
        public static double GetMean(this HistogramBase histogram)
        {
            var totalCount = histogram.TotalCount;

            if (totalCount == 0)
            {
                return(0);
            }

            var totalValue = histogram.RecordedValues().Select(hiv => hiv.TotalValueToThisValue).LastOrDefault();

            return((totalValue * 1.0) / totalCount);
        }
예제 #7
0
 /// <summary>
 /// Get a new instance of an interval histogram, which will include a stable, consistent view of all value counts accumulated since the last interval histogram was taken.
 /// Calling <see cref="GetIntervalHistogram()"/> will reset the value counts, and start accumulating value counts for the next interval.
 /// </summary>
 /// <param name="histogramToRecycle">a previously returned interval histogram that may be recycled to avoid allocation and copy operations.</param>
 /// <returns>A histogram containing the value counts accumulated since the last interval histogram was taken.</returns>
 /// <remarks>
 /// <see cref="GetIntervalHistogram(HistogramBase)"/> accepts a previously returned interval histogram that can be recycled internally to avoid allocation and content copying operations.
 /// It is therefore significantly more efficient for repeated use than <see cref="GetIntervalHistogram()"/> and <see cref="GetIntervalHistogramInto(HistogramBase)"/>.
 /// The provided <paramref name="histogramToRecycle"/> must be either be null or an interval histogram returned by a previous call to <see cref="GetIntervalHistogram(HistogramBase)"/> or <see cref="GetIntervalHistogram()"/>.
 /// NOTE: The caller is responsible for not recycling the same returned interval histogram more than once.
 /// If the same interval histogram instance is recycled more than once, behavior is undefined.
 /// </remarks>
 public HistogramBase GetIntervalHistogram(HistogramBase histogramToRecycle)
 {
     lock (_gate)
     {
         // Verify that replacement histogram can validly be used as an inactive histogram replacement:
         ValidateFitAsReplacementHistogram(histogramToRecycle);
         _inactiveHistogram = histogramToRecycle;
         PerformIntervalSample();
         var sampledHistogram = _inactiveHistogram;
         _inactiveHistogram = null; // Once we expose the sample, we can't reuse it internally until it is recycled
         return(sampledHistogram);
     }
 }
예제 #8
0
        /// <summary>
        /// Get the computed standard deviation of all recorded values in the histogram
        /// </summary>
        /// <returns>the standard deviation (in value units) of the histogram data</returns>
        public static double GetStdDeviation(this HistogramBase histogram)
        {
            var mean = histogram.GetMean();
            var geometricDeviationTotal = 0.0;

            foreach (var iterationValue in histogram.RecordedValues())
            {
                double deviation = (histogram.MedianEquivalentValue(iterationValue.ValueIteratedTo) * 1.0) - mean;
                geometricDeviationTotal += (deviation * deviation) * iterationValue.CountAddedInThisIterationStep;
            }
            var stdDeviation = Math.Sqrt(geometricDeviationTotal / histogram.TotalCount);

            return(stdDeviation);
        }
예제 #9
0
        private void PerformIntervalSample()
        {
            try
            {
                _recordingPhaser.ReaderLock();

                // Make sure we have an inactive version to flip in:
                if (_inactiveHistogram == null)
                {
                    _inactiveHistogram = _histogramFactory(_instanceId,
                                                           _activeHistogram.LowestTrackableValue,
                                                           _activeHistogram.HighestTrackableValue,
                                                           _activeHistogram.NumberOfSignificantValueDigits);
                }

                _inactiveHistogram.Reset();

                // Swap active and inactive histograms:
                var tempHistogram = _inactiveHistogram;
                _inactiveHistogram = _activeHistogram;
                _activeHistogram   = tempHistogram;

                // Mark end time of previous interval and start time of new one:
                var now = DateTime.Now.MillisecondsSinceUnixEpoch();
                _activeHistogram.StartTimeStamp = now;
                _inactiveHistogram.EndTimeStamp = now;

                // Make sure we are not in the middle of recording a value on the previously active histogram:

                // Flip phase to make sure no recordings that were in flight pre-flip are still active:
                _recordingPhaser.FlipPhase(TimeSpan.FromMilliseconds(0.5));
            }
            finally
            {
                _recordingPhaser.ReaderUnlock();
            }
        }
예제 #10
0
 /// <summary>
 /// 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.
 /// </summary>
 /// <param name="histogram">The histogram to operate on</param>
 /// <param name="value">The given value</param>
 /// <returns>The highest value that is equivalent to the given value within the histogram's resolution.</returns>
 public static long HighestEquivalentValue(this HistogramBase histogram, long value)
 {
     return(histogram.NextNonEquivalentValue(value) - 1);
 }
예제 #11
0
        /// <summary>
        /// Get the highest recorded value level in the histogram
        /// </summary>
        /// <returns>the Max value recorded in the histogram</returns>
        public static long GetMaxValue(this HistogramBase histogram)
        {
            var max = histogram.RecordedValues().Select(hiv => hiv.ValueIteratedTo).LastOrDefault();

            return(histogram.HighestEquivalentValue(max));
        }
예제 #12
0
 /// <summary>
 /// Provide a means of iterating through histogram values according to percentile levels.
 /// The iteration is performed in steps that start at 0% and reduce their distance to 100% according to the
 /// <paramref name="percentileTicksPerHalfDistance"/> parameter, ultimately reaching 100% when all recorded
 /// histogram values are exhausted.
 /// </summary>
 /// <param name="histogram">The histogram to operate on</param>
 /// <param name="percentileTicksPerHalfDistance">
 /// The number of iteration steps per half-distance to 100%.
 /// </param>
 /// <returns>
 /// An enumerator of <see cref="HistogramIterationValue"/> through the histogram using a
 /// <see cref="PercentileEnumerator"/>.
 /// </returns>
 public static IEnumerable <HistogramIterationValue> Percentiles(this HistogramBase histogram, int percentileTicksPerHalfDistance)
 {
     return(new PercentileEnumerable(histogram, percentileTicksPerHalfDistance));
 }
예제 #13
0
 //Optimization. This simple method should be in-lined by the JIT compiler, allowing hot path `GetBucketIndex(long, long, int)` to become static. -LC
 private int GetBucketIndex(long value)
 {
     return(HistogramBase.GetBucketIndex(value, _subBucketMask, _bucketIndexOffset));
 }