
de.fau.cs.osr.utils.MovingAverage Maven / Gradle / Ivy
/**
* Copyright 2011 The Open Source Research Group,
* University of Erlangen-Nürnberg
*
* Licensed 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 de.fau.cs.osr.utils;
public class MovingAverage
{
private int movingAvgBucketSizeMs;
private boolean firstUpdateValid = false;
private long firstUpdate = 0;
private int firstBucket = 0;
private long currentBucketSum = 0;
private long currentBucketCount = 0;
private final RingBuffer buffer;
private double bufferSum = 0;
private long bufferCount = 0;
// =========================================================================
public MovingAverage(int movingAvgWindowMs, int movingAvgBucketSizeMs)
{
this.movingAvgBucketSizeMs = movingAvgBucketSizeMs;
this.buffer = new RingBuffer(movingAvgWindowMs / movingAvgBucketSizeMs);
}
// =========================================================================
// For time measurement only
public static long startTimeNs()
{
return System.nanoTime();
}
public void stopTime(long startTimeNs)
{
long now = System.nanoTime();
update(now, delta(startTimeNs, now));
}
/**
* @return Delta in milliseconds times factor.
*/
public double stopTime(long startTimeNs, double factor)
{
long now = System.nanoTime();
double delta = delta(startTimeNs, now) * factor;
update(now, (long) delta);
return delta / (1000. * 1000.);
}
public double getAverageInSec()
{
// nano -> micro -> milli -> si
return getAverage() / (1000. * 1000. * 1000.);
}
// =========================================================================
// For measurement in general
public synchronized double getAverage()
{
long count = bufferCount;
double sum = bufferSum;
if (currentBucketCount > 0)
{
sum += currentBucketSum / (double) currentBucketCount;
count++;
}
if (count == 0)
return 0;
return sum / (double) count;
}
public synchronized void update(long nowNs, long value)
{
if (firstUpdateValid)
{
long sinceFirstUpdate = delta(firstUpdate, nowNs) / (1000L * 1000);
int bucket = (int) (sinceFirstUpdate / movingAvgBucketSizeMs);
int advance = bucket - firstBucket;
if (advance > buffer.getCapacity())
{
reset();
}
else if (advance > 0)
{
firstBucket += advance;
if (currentBucketCount > 0)
{
nextBucket(currentBucketSum / (double) currentBucketCount);
advance -= 1;
currentBucketSum = 0;
currentBucketCount = 0;
}
for (int i = 0; i < advance; ++i)
nextBucket(null);
}
}
else
{
firstUpdate = nowNs;
firstUpdateValid = true;
}
currentBucketSum += value;
currentBucketCount++;
}
public synchronized void reset()
{
buffer.clear();
bufferSum = 0;
bufferCount = 0;
currentBucketSum = 0;
currentBucketCount = 0;
firstUpdateValid = false;
firstBucket = 0;
}
// =========================================================================
private void nextBucket(Double average)
{
Double oldest = null;
if (buffer.willOverwrite())
oldest = buffer.getOldest();
buffer.add(average);
if (average != null)
{
bufferSum += average;
bufferCount++;
}
if (oldest != null)
{
bufferSum -= oldest;
bufferCount--;
}
}
private long delta(long startTime, long now)
{
return now - startTime;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy