Example #1
0
        /// <summary>
        /// Produce textual representation of the value distribution of histogram data by percentile.
        /// The distribution is output with exponentially increasing resolution, with each exponentially decreasing
        /// half-distance containing <paramref name="percentileTicksPerHalfDistance"/> percentile reporting tick points.
        /// </summary>
        /// <param name="histogram">The histogram to operate on</param>
        /// <param name="writer">The <see cref="TextWriter"/> into which the distribution will be output</param>
        /// <param name="percentileTicksPerHalfDistance">
        /// The number of reporting points per exponentially decreasing half-distance
        /// </param>
        /// <param name="outputValueUnitScalingRatio">
        /// The scaling factor by which to divide histogram recorded values units in output.
        /// Use the <see cref="OutputScalingFactor"/> constant values to help choose an appropriate output measurement.
        /// </param>
        /// <param name="useCsvFormat">Output in CSV (Comma Separated Values) format if <c>true</c>, else use plain text form.</param>
        public static void OutputPercentileDistribution(this HistogramBase histogram,
                                                        TextWriter writer,
                                                        int percentileTicksPerHalfDistance = 5,
                                                        double outputValueUnitScalingRatio = OutputScalingFactor.None,
                                                        bool useCsvFormat = false)
        {
            var formatter = useCsvFormat
                ? (IOutputFormatter) new CsvOutputFormatter(writer, histogram.NumberOfSignificantValueDigits, outputValueUnitScalingRatio)
                : (IOutputFormatter) new HgrmOutputFormatter(writer, histogram.NumberOfSignificantValueDigits, outputValueUnitScalingRatio);

            try
            {
                formatter.WriteHeader();
                foreach (var iterationValue in histogram.Percentiles(percentileTicksPerHalfDistance))
                {
                    formatter.WriteValue(iterationValue);
                }
                formatter.WriteFooter(histogram);
            }
            catch (ArgumentOutOfRangeException)
            {
                // Overflow conditions on histograms can lead to ArgumentOutOfRangeException on iterations:
                if (histogram.HasOverflowed())
                {
                    writer.Write("# Histogram counts indicate OVERFLOW values");
                }
                else
                {
                    // Re-throw if reason is not a known overflow:
                    throw;
                }
            }
        }
        /// <summary>
        /// Produce textual representation of the value distribution of histogram data by percentile.
        /// The distribution is output with exponentially increasing resolution, with each exponentially decreasing
        /// half-distance containing <paramref name="percentileTicksPerHalfDistance"/> percentile reporting tick points.
        /// </summary>
        /// <param name="histogram">The histogram to operate on</param>
        /// <param name="printStream">Stream into which the distribution will be output</param>
        /// <param name="percentileTicksPerHalfDistance">
        /// The number of reporting points per exponentially decreasing half-distance
        /// </param>
        /// <param name="outputValueUnitScalingRatio">
        /// The scaling factor by which to divide histogram recorded values units in output.
        /// Use the <see cref="OutputScalingFactor"/> constant values to help choose an appropriate output measurement.
        /// </param>
        /// <param name="useCsvFormat">Output in CSV (Comma Separated Values) format if <c>true</c>, else use plain text form.</param>
        public static void OutputPercentileDistribution(this HistogramBase histogram,
                                                        TextWriter printStream,
                                                        int percentileTicksPerHalfDistance = 5,
                                                        double outputValueUnitScalingRatio = OutputScalingFactor.TicksToMilliseconds,
                                                        bool useCsvFormat = false)
        {
            if (useCsvFormat)
            {
                printStream.Write("\"Value\",\"Percentile\",\"TotalCount\",\"1/(1-Percentile)\"\n");
            }
            else
            {
                printStream.Write("{0,12} {1,14} {2,10} {3,14}\n\n", "Value", "Percentile", "TotalCount", "1/(1-Percentile)");
            }


            string percentileFormatString;
            string lastLinePercentileFormatString;

            if (useCsvFormat)
            {
                percentileFormatString         = "{0:F" + histogram.NumberOfSignificantValueDigits + "},{1:F12},{2},{3:F2}\n";
                lastLinePercentileFormatString = "{0:F" + histogram.NumberOfSignificantValueDigits + "},{1:F12},{2},Infinity\n";
            }
            else
            {
                percentileFormatString         = "{0,12:F" + histogram.NumberOfSignificantValueDigits + "}" + " {1,2:F12} {2,10} {3,14:F2}\n";
                lastLinePercentileFormatString = "{0,12:F" + histogram.NumberOfSignificantValueDigits + "} {1,2:F12} {2,10}\n";
            }

            try
            {
                foreach (var iterationValue in histogram.Percentiles(percentileTicksPerHalfDistance))
                {
                    if (iterationValue.PercentileLevelIteratedTo != 100.0D)
                    {
                        printStream.Write(percentileFormatString,
                                          iterationValue.ValueIteratedTo / outputValueUnitScalingRatio,
                                          iterationValue.PercentileLevelIteratedTo / 100.0D,
                                          iterationValue.TotalCountToThisValue,
                                          1 / (1.0D - (iterationValue.PercentileLevelIteratedTo / 100.0D)));
                    }
                    else
                    {
                        printStream.Write(lastLinePercentileFormatString,
                                          iterationValue.ValueIteratedTo / outputValueUnitScalingRatio,
                                          iterationValue.PercentileLevelIteratedTo / 100.0D,
                                          iterationValue.TotalCountToThisValue);
                    }
                }

                if (!useCsvFormat)
                {
                    // Calculate and output mean and std. deviation.
                    // Note: mean/std. deviation numbers are very often completely irrelevant when
                    // data is extremely non-normal in distribution (e.g. in cases of strong multi-modal
                    // response time distribution associated with GC pauses). However, reporting these numbers
                    // can be very useful for contrasting with the detailed percentile distribution
                    // reported by outputPercentileDistribution(). It is not at all surprising to find
                    // percentile distributions where results fall many tens or even hundreds of standard
                    // deviations away from the mean - such results simply indicate that the data sampled
                    // exhibits a very non-normal distribution, highlighting situations for which the std.
                    // deviation metric is a useless indicator.

                    var mean         = histogram.GetMean() / outputValueUnitScalingRatio;
                    var stdDeviation = histogram.GetStdDeviation() / outputValueUnitScalingRatio;
                    printStream.Write("#[Mean    = {0,12:F" + histogram.NumberOfSignificantValueDigits + "}, " +
                                      "StdDeviation   = {1,12:F" + histogram.NumberOfSignificantValueDigits + "}]\n", mean, stdDeviation);
                    printStream.Write("#[Max     = {0,12:F" + histogram.NumberOfSignificantValueDigits + "}, Total count    = {1,12}]\n",
                                      histogram.GetMaxValue() / outputValueUnitScalingRatio, histogram.TotalCount);
                    printStream.Write("#[Buckets = {0,12}, SubBuckets     = {1,12}]\n",
                                      histogram.BucketCount, histogram.SubBucketCount);
                }
            }
            catch (ArgumentOutOfRangeException)
            {
                // Overflow conditions on histograms can lead to ArgumentOutOfRangeException on iterations:
                if (histogram.HasOverflowed())
                {
                    printStream.Write("# Histogram counts indicate OVERFLOW values");
                }
                else
                {
                    // Re-throw if reason is not a known overflow:
                    throw;
                }
            }
        }