Created
March 5, 2014 17:20
-
-
Save yukim/9371796 to your computer and use it in GitHub Desktop.
CASSANDRA-6591 EWMA test
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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