Skip to content

Instantly share code, notes, and snippets.

@yukim
Created March 5, 2014 17:20
Show Gist options
  • Save yukim/9371796 to your computer and use it in GitHub Desktop.
Save yukim/9371796 to your computer and use it in GitHub Desktop.
CASSANDRA-6591 EWMA test
package org.apache.cassandra;
import java.util.concurrent.TimeUnit;
import com.yammer.metrics.stats.EWMA;
import static java.lang.Math.exp;
public class EWMATest
{
public static void main(String[] args)
{
EWMA m1 = EWMA.oneMinuteEWMA();
EWMA m2 = EWMA.oneMinuteEWMA();
DoubleEWMA r = DoubleEWMA.oneMinuteEWMA();
int hit = 0;
int req = 0;
System.out.println("min,average,hit mva,rate mva,hit mva/rate mva,hit rate mva");
System.out.println("0,0,0,0,0,0");
// simulate for 30min (1 loop = 1 sec)
for (int i = 1; i <= 60 * 30; i++)
{
if (i <= 60)
{
hit += 1;
m1.update(1);
}
req += 1;
m2.update(1);
r.update(((double)hit)/req);
// tick every 5 sec
if (i % 5 == 0)
{
m1.tick();
m2.tick();
r.tick();
}
// display every minutes
if (i % 60 == 0)
{
double hitMVA = m1.rate(TimeUnit.SECONDS);
double reqMVA = m2.rate(TimeUnit.SECONDS);
System.out.println((i/60) + "," + ((double)hit)/req + "," + hitMVA + "," + reqMVA + "," + hitMVA / reqMVA + "," + r.rate(TimeUnit.SECONDS));
}
}
}
/* test only. not thread safe */
public static class DoubleEWMA
{
private static final int INTERVAL = 5;
private static final double SECONDS_PER_MINUTE = 60.0;
private static final int ONE_MINUTE = 1;
private static final int FIVE_MINUTES = 5;
private static final int FIFTEEN_MINUTES = 15;
private static final double M1_ALPHA = 1 - exp(-INTERVAL / SECONDS_PER_MINUTE / ONE_MINUTE);
private static final double M5_ALPHA = 1 - exp(-INTERVAL / SECONDS_PER_MINUTE / FIVE_MINUTES);
private static final double M15_ALPHA = 1 - exp(-INTERVAL / SECONDS_PER_MINUTE / FIFTEEN_MINUTES);
private volatile boolean initialized = false;
private volatile double rate = 0.0;
private double uncounted = 0.0;
private final double alpha, interval;
public static DoubleEWMA oneMinuteEWMA() {
return new DoubleEWMA(M1_ALPHA, INTERVAL, TimeUnit.SECONDS);
}
public static DoubleEWMA fiveMinuteEWMA() {
return new DoubleEWMA(M5_ALPHA, INTERVAL, TimeUnit.SECONDS);
}
/**
* Create a new EWMA with a specific smoothing constant.
*
* @param alpha the smoothing constant
* @param interval the expected tick interval
* @param intervalUnit the time unit of the tick interval
*/
public DoubleEWMA(double alpha, long interval, TimeUnit intervalUnit) {
this.interval = intervalUnit.toNanos(interval);
this.alpha = alpha;
}
/**
* Update the moving average with a new value.
*
* @param n the new value
*/
public void update(double n) {
uncounted += n;
}
/**
* Mark the passage of time and decay the current rate accordingly.
*/
public void tick() {
final double instantRate = uncounted / interval;
uncounted = 0;
if (initialized) {
rate += (alpha * (instantRate - rate));
} else {
rate = instantRate;
initialized = true;
}
}
/**
* Returns the rate in the given units of time.
*
* @param rateUnit the unit of time
* @return the rate
*/
public double rate(TimeUnit rateUnit) {
return rate * (double) rateUnit.toNanos(1);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment