HBASE-19450 Addendum Limit logging of chore execution time at INFO to once per 5 minutes.
* Ensure MovingAverage related classes are IA.Private * Move trace logging into MovingAverage class Signed-off-by: Duo Zhang <zhangduo@apache.org>
This commit is contained in:
parent
e60764f5a1
commit
b292ffd14d
|
@ -81,7 +81,9 @@ public abstract class ScheduledChore implements Runnable {
|
||||||
*/
|
*/
|
||||||
private final Stoppable stopper;
|
private final Stoppable stopper;
|
||||||
|
|
||||||
private final MovingAverage<Void> timeMeasurement = new WindowMovingAverage();
|
private final MovingAverage<Void> timeMeasurement;
|
||||||
|
private static final long FIVE_MINUTES_IN_NANOS = TimeUnit.MINUTES.toNanos(5L);
|
||||||
|
private long lastLog = System.nanoTime();
|
||||||
|
|
||||||
interface ChoreServicer {
|
interface ChoreServicer {
|
||||||
/**
|
/**
|
||||||
|
@ -122,11 +124,7 @@ public abstract class ScheduledChore implements Runnable {
|
||||||
@InterfaceAudience.Private
|
@InterfaceAudience.Private
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
protected ScheduledChore() {
|
protected ScheduledChore() {
|
||||||
this.name = null;
|
this("TestChore", null, 0, DEFAULT_INITIAL_DELAY, DEFAULT_TIME_UNIT);
|
||||||
this.stopper = null;
|
|
||||||
this.period = 0;
|
|
||||||
this.initialDelay = DEFAULT_INITIAL_DELAY;
|
|
||||||
this.timeUnit = DEFAULT_TIME_UNIT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -167,6 +165,7 @@ public abstract class ScheduledChore implements Runnable {
|
||||||
this.period = period;
|
this.period = period;
|
||||||
this.initialDelay = initialDelay < 0 ? 0 : initialDelay;
|
this.initialDelay = initialDelay < 0 ? 0 : initialDelay;
|
||||||
this.timeUnit = unit;
|
this.timeUnit = unit;
|
||||||
|
this.timeMeasurement = new WindowMovingAverage(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -191,8 +190,11 @@ public abstract class ScheduledChore implements Runnable {
|
||||||
chore();
|
chore();
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
LOG.info(String.format("%s average execution time: %.2f ns.", getName(),
|
if (LOG.isInfoEnabled() && (System.nanoTime() - lastLog > FIVE_MINUTES_IN_NANOS)) {
|
||||||
timeMeasurement.getAverageTime()));
|
LOG.info("{} average execution time: {} ns.", getName(),
|
||||||
|
(long)(timeMeasurement.getAverageTime()));
|
||||||
|
lastLog = System.nanoTime();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
if (LOG.isErrorEnabled()) LOG.error("Caught error", t);
|
if (LOG.isErrorEnabled()) LOG.error("Caught error", t);
|
||||||
|
|
|
@ -24,26 +24,26 @@ import org.apache.yetus.audience.InterfaceAudience;
|
||||||
* EMA is similar to {@link WeightedMovingAverage} in weighted, but the weighting factor decrease
|
* EMA is similar to {@link WeightedMovingAverage} in weighted, but the weighting factor decrease
|
||||||
* exponentially. It brings benefits that it is more sensitive, and can see the trends easily.
|
* exponentially. It brings benefits that it is more sensitive, and can see the trends easily.
|
||||||
*/
|
*/
|
||||||
@InterfaceAudience.Public
|
@InterfaceAudience.Private
|
||||||
public class ExponentialMovingAverage extends WindowMovingAverage {
|
public class ExponentialMovingAverage extends WindowMovingAverage {
|
||||||
private double alpha;
|
private double alpha;
|
||||||
private double previousAverage;
|
private double previousAverage;
|
||||||
private double currentAverage;
|
private double currentAverage;
|
||||||
|
|
||||||
public ExponentialMovingAverage() {
|
public ExponentialMovingAverage(String label) {
|
||||||
this(DEFAULT_SIZE);
|
this(label, DEFAULT_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExponentialMovingAverage(double alpha) {
|
public ExponentialMovingAverage(String label, double alpha) {
|
||||||
this(DEFAULT_SIZE, alpha);
|
this(label, DEFAULT_SIZE, alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExponentialMovingAverage(int size) {
|
public ExponentialMovingAverage(String label, int size) {
|
||||||
this(size, (double) 2 / (1 + size));
|
this(label, size, (double) 2 / (1 + size));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExponentialMovingAverage(int size, double alpha) {
|
public ExponentialMovingAverage(String label, int size, double alpha) {
|
||||||
super(size);
|
super(label, size);
|
||||||
this.previousAverage = -1.0;
|
this.previousAverage = -1.0;
|
||||||
this.currentAverage = 0.0;
|
this.currentAverage = 0.0;
|
||||||
this.alpha = alpha;
|
this.alpha = alpha;
|
||||||
|
|
|
@ -29,10 +29,16 @@ import org.slf4j.LoggerFactory;
|
||||||
* <br>
|
* <br>
|
||||||
* In different situation, different {@link MovingAverage} algorithm can be used based on needs.
|
* In different situation, different {@link MovingAverage} algorithm can be used based on needs.
|
||||||
*/
|
*/
|
||||||
@InterfaceAudience.Public
|
@InterfaceAudience.Private
|
||||||
public abstract class MovingAverage<T> {
|
public abstract class MovingAverage<T> {
|
||||||
private final static Logger LOG = LoggerFactory.getLogger(MovingAverage.class);
|
private final static Logger LOG = LoggerFactory.getLogger(MovingAverage.class);
|
||||||
|
|
||||||
|
protected final String label;
|
||||||
|
|
||||||
|
protected MovingAverage(String label) {
|
||||||
|
this.label = label;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mark start time of an execution.
|
* Mark start time of an execution.
|
||||||
* @return time in ns.
|
* @return time in ns.
|
||||||
|
@ -57,12 +63,12 @@ public abstract class MovingAverage<T> {
|
||||||
*/
|
*/
|
||||||
public T measure(TimeMeasurable<T> measurable) {
|
public T measure(TimeMeasurable<T> measurable) {
|
||||||
long startTime = start();
|
long startTime = start();
|
||||||
LOG.debug("Start to measure at: {} ns.", startTime);
|
LOG.trace("{} - start to measure at: {} ns.", label, startTime);
|
||||||
// Here may throw exceptions which should be taken care by caller, not here.
|
// Here may throw exceptions which should be taken care by caller, not here.
|
||||||
// If exception occurs, this time wouldn't count.
|
// If exception occurs, this time wouldn't count.
|
||||||
T result = measurable.measure();
|
T result = measurable.measure();
|
||||||
long elapsed = stop(startTime);
|
long elapsed = stop(startTime);
|
||||||
LOG.debug("Elapse: {} ns.", elapsed);
|
LOG.trace("{} - elapse: {} ns.", label, elapsed);
|
||||||
updateMostRecentTime(elapsed);
|
updateMostRecentTime(elapsed);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,12 +23,13 @@ import org.apache.yetus.audience.InterfaceAudience;
|
||||||
/**
|
/**
|
||||||
* SMA measure the overall average execution time of a specific method.
|
* SMA measure the overall average execution time of a specific method.
|
||||||
*/
|
*/
|
||||||
@InterfaceAudience.Public
|
@InterfaceAudience.Private
|
||||||
public class SimpleMovingAverage extends MovingAverage {
|
public class SimpleMovingAverage extends MovingAverage {
|
||||||
private double averageTime = 0.0;
|
private double averageTime = 0.0;
|
||||||
protected long count = 0;
|
protected long count = 0;
|
||||||
|
|
||||||
public SimpleMovingAverage() {
|
public SimpleMovingAverage(String label) {
|
||||||
|
super(label);
|
||||||
this.averageTime = 0.0;
|
this.averageTime = 0.0;
|
||||||
this.count = 0;
|
this.count = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ import org.apache.yetus.audience.InterfaceAudience;
|
||||||
* Methods that implement this interface can be measured elapsed time.
|
* Methods that implement this interface can be measured elapsed time.
|
||||||
* It works together with {@link MovingAverage} to take effect.
|
* It works together with {@link MovingAverage} to take effect.
|
||||||
*/
|
*/
|
||||||
@InterfaceAudience.Public
|
@InterfaceAudience.Private
|
||||||
public interface TimeMeasurable<T> {
|
public interface TimeMeasurable<T> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -24,17 +24,17 @@ import org.apache.yetus.audience.InterfaceAudience;
|
||||||
* Different from SMA {@link SimpleMovingAverage}, WeightedMovingAverage gives each data different
|
* Different from SMA {@link SimpleMovingAverage}, WeightedMovingAverage gives each data different
|
||||||
* weight. And it is based on {@link WindowMovingAverage}, such that it only focus on the last N.
|
* weight. And it is based on {@link WindowMovingAverage}, such that it only focus on the last N.
|
||||||
*/
|
*/
|
||||||
@InterfaceAudience.Public
|
@InterfaceAudience.Private
|
||||||
public class WeightedMovingAverage extends WindowMovingAverage {
|
public class WeightedMovingAverage extends WindowMovingAverage {
|
||||||
private int[] coefficient;
|
private int[] coefficient;
|
||||||
private int denominator;
|
private int denominator;
|
||||||
|
|
||||||
public WeightedMovingAverage() {
|
public WeightedMovingAverage(String label) {
|
||||||
this(DEFAULT_SIZE);
|
this(label, DEFAULT_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public WeightedMovingAverage(int size) {
|
public WeightedMovingAverage(String label, int size) {
|
||||||
super(size);
|
super(label, size);
|
||||||
int length = getNumberOfStatistics();
|
int length = getNumberOfStatistics();
|
||||||
denominator = length * (length + 1) / 2;
|
denominator = length * (length + 1) / 2;
|
||||||
coefficient = new int[length];
|
coefficient = new int[length];
|
||||||
|
|
|
@ -24,7 +24,7 @@ import org.apache.yetus.audience.InterfaceAudience;
|
||||||
* Instead of calculate a whole time average, this class focus on the last N.
|
* Instead of calculate a whole time average, this class focus on the last N.
|
||||||
* The last N is stored in a circle array.
|
* The last N is stored in a circle array.
|
||||||
*/
|
*/
|
||||||
@InterfaceAudience.Public
|
@InterfaceAudience.Private
|
||||||
public class WindowMovingAverage extends MovingAverage {
|
public class WindowMovingAverage extends MovingAverage {
|
||||||
protected final static int DEFAULT_SIZE = 5;
|
protected final static int DEFAULT_SIZE = 5;
|
||||||
|
|
||||||
|
@ -35,11 +35,12 @@ public class WindowMovingAverage extends MovingAverage {
|
||||||
// If it travels a round.
|
// If it travels a round.
|
||||||
protected boolean oneRound;
|
protected boolean oneRound;
|
||||||
|
|
||||||
public WindowMovingAverage() {
|
public WindowMovingAverage(String label) {
|
||||||
this(DEFAULT_SIZE);
|
this(label, DEFAULT_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public WindowMovingAverage(int size) {
|
public WindowMovingAverage(String label, int size) {
|
||||||
|
super(label);
|
||||||
this.lastN = new long[size <= 0 ? DEFAULT_SIZE : size];
|
this.lastN = new long[size <= 0 ? DEFAULT_SIZE : size];
|
||||||
this.mostRecent = -1;
|
this.mostRecent = -1;
|
||||||
this.oneRound = false;
|
this.oneRound = false;
|
||||||
|
|
|
@ -22,8 +22,10 @@ import org.apache.hadoop.hbase.HBaseClassTestRule;
|
||||||
import org.apache.hadoop.hbase.testclassification.SmallTests;
|
import org.apache.hadoop.hbase.testclassification.SmallTests;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.ClassRule;
|
import org.junit.ClassRule;
|
||||||
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.experimental.categories.Category;
|
import org.junit.experimental.categories.Category;
|
||||||
|
import org.junit.rules.TestName;
|
||||||
|
|
||||||
@Category(SmallTests.class)
|
@Category(SmallTests.class)
|
||||||
public class TestMovingAverage {
|
public class TestMovingAverage {
|
||||||
|
@ -32,12 +34,15 @@ public class TestMovingAverage {
|
||||||
public static final HBaseClassTestRule CLASS_RULE =
|
public static final HBaseClassTestRule CLASS_RULE =
|
||||||
HBaseClassTestRule.forClass(TestMovingAverage.class);
|
HBaseClassTestRule.forClass(TestMovingAverage.class);
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public TestName name = new TestName();
|
||||||
|
|
||||||
private long[] data = {1, 12, 13, 24, 25, 26, 37, 38, 39, 40};
|
private long[] data = {1, 12, 13, 24, 25, 26, 37, 38, 39, 40};
|
||||||
private double delta = 0.1;
|
private double delta = 0.1;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSimpleMovingAverage() throws Exception {
|
public void testSimpleMovingAverage() throws Exception {
|
||||||
MovingAverage<?> algorithm = new SimpleMovingAverage();
|
MovingAverage<?> algorithm = new SimpleMovingAverage(name.getMethodName());
|
||||||
int index = 0;
|
int index = 0;
|
||||||
// [1, 12, 13, 24]
|
// [1, 12, 13, 24]
|
||||||
int bound = 4;
|
int bound = 4;
|
||||||
|
@ -67,7 +72,7 @@ public class TestMovingAverage {
|
||||||
@Test
|
@Test
|
||||||
public void testWindowMovingAverage() throws Exception {
|
public void testWindowMovingAverage() throws Exception {
|
||||||
// Default size is 5.
|
// Default size is 5.
|
||||||
MovingAverage<?> algorithm = new WindowMovingAverage();
|
MovingAverage<?> algorithm = new WindowMovingAverage(name.getMethodName());
|
||||||
int index = 0;
|
int index = 0;
|
||||||
// [1, 12, 13, 24]
|
// [1, 12, 13, 24]
|
||||||
int bound = 4;
|
int bound = 4;
|
||||||
|
@ -97,7 +102,7 @@ public class TestMovingAverage {
|
||||||
@Test
|
@Test
|
||||||
public void testWeightedMovingAverage() throws Exception {
|
public void testWeightedMovingAverage() throws Exception {
|
||||||
// Default size is 5.
|
// Default size is 5.
|
||||||
MovingAverage<?> algorithm = new WeightedMovingAverage();
|
MovingAverage<?> algorithm = new WeightedMovingAverage(name.getMethodName());
|
||||||
int index = 0;
|
int index = 0;
|
||||||
// [1, 12, 13, 24]
|
// [1, 12, 13, 24]
|
||||||
int bound = 4;
|
int bound = 4;
|
||||||
|
@ -127,7 +132,7 @@ public class TestMovingAverage {
|
||||||
@Test
|
@Test
|
||||||
public void testExponentialMovingAverage() throws Exception {
|
public void testExponentialMovingAverage() throws Exception {
|
||||||
// [1, 12, 13, 24, 25, 26, 37, 38, 39, 40]
|
// [1, 12, 13, 24, 25, 26, 37, 38, 39, 40]
|
||||||
MovingAverage<?> algorithm = new ExponentialMovingAverage();
|
MovingAverage<?> algorithm = new ExponentialMovingAverage(name.getMethodName());
|
||||||
int index = 0;
|
int index = 0;
|
||||||
int bound = 5;
|
int bound = 5;
|
||||||
for (; index < bound; index++) {
|
for (; index < bound; index++) {
|
||||||
|
|
Loading…
Reference in New Issue