You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

139 lines
4.8 KiB

/*
* This is a TypeScript port of the original Java version, which was written by
* Gil Tene as described in
* https://github.com/HdrHistogram/HdrHistogram
* and released to the public domain, as explained at
* http://creativecommons.org/publicdomain/zero/1.0/
*/
import JsHistogram from "./JsHistogram";
import HistogramIterationValue from "./HistogramIterationValue";
/**
* Used for iterating through histogram values.
*/
abstract class JsHistogramIterator /* implements Iterator<HistogramIterationValue> */ {
histogram: JsHistogram;
savedHistogramTotalRawCount: number;
currentIndex: number;
currentValueAtIndex: number;
nextValueAtIndex: number;
prevValueIteratedTo: number;
totalCountToPrevIndex: number;
totalCountToCurrentIndex: number;
totalValueToCurrentIndex: number;
arrayTotalCount: number;
countAtThisValue: number;
private freshSubBucket: boolean;
currentIterationValue: HistogramIterationValue = new HistogramIterationValue();
resetIterator(histogram: JsHistogram) {
this.histogram = histogram;
this.savedHistogramTotalRawCount = histogram.totalCount;
this.arrayTotalCount = histogram.totalCount;
this.currentIndex = 0;
this.currentValueAtIndex = 0;
this.nextValueAtIndex = Math.pow(2, histogram.unitMagnitude);
this.prevValueIteratedTo = 0;
this.totalCountToPrevIndex = 0;
this.totalCountToCurrentIndex = 0;
this.totalValueToCurrentIndex = 0;
this.countAtThisValue = 0;
this.freshSubBucket = true;
this.currentIterationValue.reset();
}
/**
* Returns true if the iteration has more elements. (In other words, returns true if next would return an
* element rather than throwing an exception.)
*
* @return true if the iterator has more elements.
*/
public hasNext(): boolean {
if (this.histogram.totalCount !== this.savedHistogramTotalRawCount) {
throw "Concurrent Modification Exception";
}
return this.totalCountToCurrentIndex < this.arrayTotalCount;
}
/**
* Returns the next element in the iteration.
*
* @return the {@link HistogramIterationValue} associated with the next element in the iteration.
*/
public next(): HistogramIterationValue {
// Move through the sub buckets and buckets until we hit the next reporting level:
while (!this.exhaustedSubBuckets()) {
this.countAtThisValue = this.histogram.getCountAtIndex(this.currentIndex);
if (this.freshSubBucket) {
// Don't add unless we've incremented since last bucket...
this.totalCountToCurrentIndex += this.countAtThisValue;
this.totalValueToCurrentIndex +=
this.countAtThisValue *
this.histogram.highestEquivalentValue(this.currentValueAtIndex);
this.freshSubBucket = false;
}
if (this.reachedIterationLevel()) {
const valueIteratedTo = this.getValueIteratedTo();
Object.assign(this.currentIterationValue, {
valueIteratedTo,
valueIteratedFrom: this.prevValueIteratedTo,
countAtValueIteratedTo: this.countAtThisValue,
countAddedInThisIterationStep:
this.totalCountToCurrentIndex - this.totalCountToPrevIndex,
totalCountToThisValue: this.totalCountToCurrentIndex,
totalValueToThisValue: this.totalValueToCurrentIndex,
percentile:
(100 * this.totalCountToCurrentIndex) / this.arrayTotalCount,
percentileLevelIteratedTo: this.getPercentileIteratedTo(),
});
this.prevValueIteratedTo = valueIteratedTo;
this.totalCountToPrevIndex = this.totalCountToCurrentIndex;
this.incrementIterationLevel();
if (this.histogram.totalCount !== this.savedHistogramTotalRawCount) {
throw new Error("Concurrent Modification Exception");
}
return this.currentIterationValue;
}
this.incrementSubBucket();
}
throw new Error("Index Out Of Bounds Exception");
}
abstract incrementIterationLevel(): void;
/**
* @return true if the current position's data should be emitted by the iterator
*/
abstract reachedIterationLevel(): boolean;
getPercentileIteratedTo(): number {
return (100 * this.totalCountToCurrentIndex) / this.arrayTotalCount;
}
getPercentileIteratedFrom(): number {
return (100 * this.totalCountToPrevIndex) / this.arrayTotalCount;
}
getValueIteratedTo(): number {
return this.histogram.highestEquivalentValue(this.currentValueAtIndex);
}
private exhaustedSubBuckets(): boolean {
return this.currentIndex >= this.histogram.countsArrayLength;
}
incrementSubBucket() {
this.freshSubBucket = true;
this.currentIndex++;
this.currentValueAtIndex = this.histogram.valueFromIndex(this.currentIndex);
this.nextValueAtIndex = this.histogram.valueFromIndex(
this.currentIndex + 1
);
}
}
export default JsHistogramIterator;