File tree Expand file tree Collapse file tree 3 files changed +67
-4
lines changed
main/java/com/codahale/metrics
test/java/com/codahale/metrics Expand file tree Collapse file tree 3 files changed +67
-4
lines changed Original file line number Diff line number Diff line change @@ -81,6 +81,14 @@ public void update(long n) {
8181 uncounted .add (n );
8282 }
8383
84+ /**
85+ * Set the rate to the smallest possible positive value. Used to avoid calling tick a large number of times.
86+ */
87+ public void reset () {
88+ uncounted .reset ();
89+ rate = Double .MIN_NORMAL ;
90+ }
91+
8492 /**
8593 * Mark the passage of time and decay the current rate accordingly.
8694 */
Original file line number Diff line number Diff line change 1111 */
1212public class ExponentialMovingAverages implements MovingAverages {
1313
14+ /**
15+ * If ticking would reduce even Long.MAX_VALUE in the 15 minute EWMA below this target then don't bother
16+ * ticking in a loop and instead reset all the EWMAs.
17+ */
18+ private static final double maxTickZeroTarget = 0.0001 ;
19+ private static final int maxTicks ;
1420 private static final long TICK_INTERVAL = TimeUnit .SECONDS .toNanos (5 );
1521
22+ static
23+ {
24+ int m3Ticks = 1 ;
25+ final EWMA m3 = EWMA .fifteenMinuteEWMA ();
26+ m3 .update (Long .MAX_VALUE );
27+ do
28+ {
29+ m3 .tick ();
30+ m3Ticks ++;
31+ }
32+ while (m3 .getRate (TimeUnit .SECONDS ) > maxTickZeroTarget );
33+ maxTicks = m3Ticks ;
34+ }
35+
1636 private final EWMA m1Rate = EWMA .oneMinuteEWMA ();
1737 private final EWMA m5Rate = EWMA .fiveMinuteEWMA ();
1838 private final EWMA m15Rate = EWMA .fifteenMinuteEWMA ();
@@ -51,10 +71,19 @@ public void tickIfNecessary() {
5171 final long newIntervalStartTick = newTick - age % TICK_INTERVAL ;
5272 if (lastTick .compareAndSet (oldTick , newIntervalStartTick )) {
5373 final long requiredTicks = age / TICK_INTERVAL ;
54- for (long i = 0 ; i < requiredTicks ; i ++) {
55- m1Rate .tick ();
56- m5Rate .tick ();
57- m15Rate .tick ();
74+ if (requiredTicks >= maxTicks ) {
75+ m1Rate .reset ();
76+ m5Rate .reset ();
77+ m15Rate .reset ();
78+ }
79+ else
80+ {
81+ for (long i = 0 ; i < requiredTicks ; i ++)
82+ {
83+ m1Rate .tick ();
84+ m5Rate .tick ();
85+ m15Rate .tick ();
86+ }
5887 }
5988 }
6089 }
Original file line number Diff line number Diff line change 1+ package com .codahale .metrics ;
2+
3+ import java .util .concurrent .TimeUnit ;
4+
5+ import org .junit .Test ;
6+
7+ import static org .junit .Assert .assertEquals ;
8+ import static org .mockito .Mockito .mock ;
9+ import static org .mockito .Mockito .when ;
10+
11+ public class ExponentialMovingAveragesTest
12+ {
13+ @ Test
14+ public void testMaxTicks ()
15+ {
16+ final Clock clock = mock (Clock .class );
17+ when (clock .getTick ()).thenReturn (0L , Long .MAX_VALUE );
18+ final ExponentialMovingAverages ema = new ExponentialMovingAverages (clock );
19+ ema .update (Long .MAX_VALUE );
20+ ema .tickIfNecessary ();
21+ final long secondNanos = TimeUnit .SECONDS .toNanos (1 );
22+ assertEquals (ema .getM1Rate (), Double .MIN_NORMAL * secondNanos , 0.0 );
23+ assertEquals (ema .getM5Rate (), Double .MIN_NORMAL * secondNanos , 0.0 );
24+ assertEquals (ema .getM15Rate (), Double .MIN_NORMAL * secondNanos , 0.0 );
25+ }
26+ }
You can’t perform that action at this time.
0 commit comments