PercentileIterator.js 3.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. const JsHistogramIterator_1 = require("./JsHistogramIterator");
  4. const { pow, floor, log2 } = Math;
  5. /**
  6. * Used for iterating through histogram values according to percentile levels. The iteration is
  7. * performed in steps that start at 0% and reduce their distance to 100% according to the
  8. * <i>percentileTicksPerHalfDistance</i> parameter, ultimately reaching 100% when all recorded histogram
  9. * values are exhausted.
  10. */
  11. class PercentileIterator extends JsHistogramIterator_1.default {
  12. /**
  13. * @param histogram The histogram this iterator will operate on
  14. * @param percentileTicksPerHalfDistance The number of equal-sized iteration steps per half-distance to 100%.
  15. */
  16. constructor(histogram, percentileTicksPerHalfDistance) {
  17. super();
  18. this.percentileTicksPerHalfDistance = 0;
  19. this.percentileLevelToIterateTo = 0;
  20. this.percentileLevelToIterateFrom = 0;
  21. this.reachedLastRecordedValue = false;
  22. this.doReset(histogram, percentileTicksPerHalfDistance);
  23. }
  24. /**
  25. * Reset iterator for re-use in a fresh iteration over the same histogram data set.
  26. *
  27. * @param percentileTicksPerHalfDistance The number of iteration steps per half-distance to 100%.
  28. */
  29. reset(percentileTicksPerHalfDistance) {
  30. this.doReset(this.histogram, percentileTicksPerHalfDistance);
  31. }
  32. doReset(histogram, percentileTicksPerHalfDistance) {
  33. super.resetIterator(histogram);
  34. this.percentileTicksPerHalfDistance = percentileTicksPerHalfDistance;
  35. this.percentileLevelToIterateTo = 0;
  36. this.percentileLevelToIterateFrom = 0;
  37. this.reachedLastRecordedValue = false;
  38. }
  39. hasNext() {
  40. if (super.hasNext())
  41. return true;
  42. if (!this.reachedLastRecordedValue && this.arrayTotalCount > 0) {
  43. this.percentileLevelToIterateTo = 100;
  44. this.reachedLastRecordedValue = true;
  45. return true;
  46. }
  47. return false;
  48. }
  49. incrementIterationLevel() {
  50. this.percentileLevelToIterateFrom = this.percentileLevelToIterateTo;
  51. // The choice to maintain fixed-sized "ticks" in each half-distance to 100% [starting
  52. // from 0%], as opposed to a "tick" size that varies with each interval, was made to
  53. // make the steps easily comprehensible and readable to humans. The resulting percentile
  54. // steps are much easier to browse through in a percentile distribution output, for example.
  55. //
  56. // We calculate the number of equal-sized "ticks" that the 0-100 range will be divided
  57. // by at the current scale. The scale is detemined by the percentile level we are
  58. // iterating to. The following math determines the tick size for the current scale,
  59. // and maintain a fixed tick size for the remaining "half the distance to 100%"
  60. // [from either 0% or from the previous half-distance]. When that half-distance is
  61. // crossed, the scale changes and the tick size is effectively cut in half.
  62. // percentileTicksPerHalfDistance = 5
  63. // percentileReportingTicks = 10,
  64. const percentileReportingTicks = this.percentileTicksPerHalfDistance *
  65. pow(2, floor(log2(100 / (100 - this.percentileLevelToIterateTo))) + 1);
  66. this.percentileLevelToIterateTo += 100 / percentileReportingTicks;
  67. }
  68. reachedIterationLevel() {
  69. if (this.countAtThisValue === 0) {
  70. return false;
  71. }
  72. const currentPercentile = (100 * this.totalCountToCurrentIndex) / this.arrayTotalCount;
  73. return currentPercentile >= this.percentileLevelToIterateTo;
  74. }
  75. getPercentileIteratedTo() {
  76. return this.percentileLevelToIterateTo;
  77. }
  78. getPercentileIteratedFrom() {
  79. return this.percentileLevelToIterateFrom;
  80. }
  81. }
  82. exports.default = PercentileIterator;
  83. //# sourceMappingURL=PercentileIterator.js.map