blob: f63208cd489400fb755e67be904b63c981da1096 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hadoop.hbase.util;
import org.apache.yetus.audience.InterfaceAudience;
/**
* This class maintains mean and variation for any sequence of input provided to it. It is
* initialized with number of rolling periods which basically means the number of past inputs whose
* data will be considered to maintain mean and variation. It will use O(N) memory to maintain these
* statistics, where N is number of look up periods it was initialized with. If zero is passed
* during initialization then it will maintain mean and variance from the start. It will use O(1)
* memory only. But note that since it will maintain mean / variance from the start the statistics
* may behave like constants and may ignore short trends. All operations are O(1) except the
* initialization which is O(N).
*/
@InterfaceAudience.Private
public class RollingStatCalculator {
private double currentSum;
private double currentSqrSum;
// Total number of data values whose statistic is currently present
private long numberOfDataValues;
private int rollingPeriod;
private int currentIndexPosition;
// to be used only if we have non-zero rolling period
private long[] dataValues;
/**
* Creates a RollingStatCalculator with given number of rolling periods.
*/
public RollingStatCalculator(int rollingPeriod) {
this.rollingPeriod = rollingPeriod;
this.dataValues = fillWithZeros(rollingPeriod);
this.currentSum = 0.0;
this.currentSqrSum = 0.0;
this.currentIndexPosition = 0;
this.numberOfDataValues = 0;
}
/**
* Inserts given data value to array of data values to be considered for statistics calculation
*/
public void insertDataValue(long data) {
// if current number of data points already equals rolling period and rolling period is
// non-zero then remove one data and update the statistics
if (numberOfDataValues >= rollingPeriod && rollingPeriod > 0) {
this.removeData(dataValues[currentIndexPosition]);
}
numberOfDataValues++;
currentSum = currentSum + (double) data;
currentSqrSum = currentSqrSum + ((double) data * data);
if (rollingPeriod > 0) {
dataValues[currentIndexPosition] = data;
currentIndexPosition = (currentIndexPosition + 1) % rollingPeriod;
}
}
/**
* Update the statistics after removing the given data value
*/
private void removeData(long data) {
currentSum = currentSum - (double) data;
currentSqrSum = currentSqrSum - ((double) data * data);
numberOfDataValues--;
}
/** Returns mean of the data values that are in the current list of data values */
public double getMean() {
return this.currentSum / (double) numberOfDataValues;
}
/** Returns deviation of the data values that are in the current list of data values */
public double getDeviation() {
double variance = (currentSqrSum - (currentSum * currentSum) / (double) (numberOfDataValues))
/ numberOfDataValues;
return Math.sqrt(variance);
}
/** Returns an array of given size initialized with zeros */
private long[] fillWithZeros(int size) {
long[] zeros = new long[size];
for (int i = 0; i < size; i++) {
zeros[i] = 0L;
}
return zeros;
}
}