/* MovingAverage.java * * Copyright 2009-2012 Comcast Interactive Media, LLC. * * 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 org.fishwife.jrugged; /** * This class implements an exponential moving average, using the algorithm described at * <a href="http://en.wikipedia.org/wiki/Moving_average">http://en.wikipedia * .org/wiki/Moving_average</a>. The average does not sample itself; it merely computes * the new average when updated with a sample by an external mechanism. */ public class MovingAverage { private final long windowMillis; private long lastMillis; private double average; /** * Construct a {@link MovingAverage}, providing the time window we want the average * over. For example, providing a value of 3,600,000 provides a moving average over * the last hour. * * @param windowMillis * the length of the sliding window in milliseconds */ public MovingAverage(final long windowMillis) { this.windowMillis = windowMillis; } /** * Updates the average with the latest measurement. * * @param sample * the latest measurement in the rolling average */ public synchronized void update(final double sample) { final long now = System.currentTimeMillis(); if (lastMillis == 0) { // first sample average = sample; lastMillis = now; return; } final long deltaTime = now - lastMillis; final double coeff = Math.exp(-1.0 * ((double) deltaTime / windowMillis)); average = (1.0 - coeff) * sample + coeff * average; lastMillis = now; } /** * Returns the last computed average value. * * @return double The calculated avg. */ public double getAverage() { return average; } }