internal HistogramData(/*final*/ AbstractHistogram histogram) { this.histogram = histogram; this.percentileIterator = new PercentileIterator(histogram, 1); this.recordedValuesIterator = new RecordedValuesIterator(histogram); this.bucketCount = histogram.bucketCount; this.subBucketCount = histogram.subBucketCount; }
/** * 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 * <i>dumpTicksPerHalf</i> percentile reporting tick points. * * @param printStream Stream into which the distribution will be output * <p> * @param percentileTicksPerHalfDistance The number of reporting points per exponentially decreasing half-distance * <p> * @param outputValueUnitScalingRatio The scaling factor by which to divide histogram recorded values units in * output * @param useCsvFormat Output in CSV format if true. Otherwise use plain text form. */ public void outputPercentileDistribution(/*final*/ TextWriter /*PrintStream*/ printStream, /*final*/ int percentileTicksPerHalfDistance = 5, /*final*/ Double outputValueUnitScalingRatio = 1000.0, 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)"); } PercentileIterator iterator = percentileIterator; iterator.reset(percentileTicksPerHalfDistance); 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 { while (iterator.hasNext()) { HistogramIterationValue iterationValue = iterator.next(); if (iterationValue.getPercentileLevelIteratedTo() != 100.0D) { printStream.Write(percentileFormatString, iterationValue.getValueIteratedTo() / outputValueUnitScalingRatio, iterationValue.getPercentileLevelIteratedTo() / 100.0D, iterationValue.getTotalCountToThisValue(), 1 / (1.0D - (iterationValue.getPercentileLevelIteratedTo() / 100.0D))); } else { printStream.Write(lastLinePercentileFormatString, iterationValue.getValueIteratedTo() / outputValueUnitScalingRatio, iterationValue.getPercentileLevelIteratedTo() / 100.0D, iterationValue.getTotalCountToThisValue()); } } 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. double mean = getMean() / outputValueUnitScalingRatio; double std_deviation = getStdDeviation() / outputValueUnitScalingRatio; printStream.Write("#[Mean = {0,12:F" + histogram.numberOfSignificantValueDigits + "}, " + "StdDeviation = {1,12:F" + histogram.numberOfSignificantValueDigits + "}]\n", mean, std_deviation); printStream.Write("#[Max = {0,12:F" + histogram.numberOfSignificantValueDigits + "}, Total count = {1,12}]\n", getMaxValue() / outputValueUnitScalingRatio, getTotalCount()); printStream.Write("#[Buckets = {0,12}, SubBuckets = {1,12}]\n", histogram.bucketCount, histogram.subBucketCount); } } catch (ArgumentOutOfRangeException e) { // Overflow conditions on histograms can lead to ArrayIndexOutOfBoundsException on iterations: if (histogram.hasOverflowed()) { //printStream.format(Locale.US, "# Histogram counts indicate OVERFLOW values"); printStream.Write("# Histogram counts indicate OVERFLOW values"); } else { // Re-throw if reason is not a known overflow: throw e; } } }