GUAVA STOPWATCH源码解析
2017-06-09 本文已影响1885人
zhuke
问题
一直在使用如下代码进行程序耗时计算和性能调试,但是对其返回值代表的具体意义却不甚了解。
Stopwatch stopwatch = Stopwatch.createStarted();
doSomething();
stopwatch.stop(); // optional
long millis = stopwatch.elapsed(MILLISECONDS);
log.info("time: " + stopwatch); // formatted string like "12.3 ms"
查看源码发现其代码并不复杂,下面就对其源码进行剖析和解释。
源码剖析
public final class Stopwatch {
private final Ticker ticker;//计时器,用于获取当前时间
private boolean isRunning;//计时器是否运行中的状态标记
private long elapsedNanos;//用于标记从计时器开启到调用统计的方法时过去的时间
private long startTick;//计时器开启的时刻时间
}
通过对elapsedNanos、startTick结合当前时刻时间,可以计算出我们所需要的程序运行流逝的时间长度。
首先来看Ticker工具类:
public static Stopwatch createStarted() {
return new Stopwatch().start();
}
Stopwatch() {
this.ticker = Ticker.systemTicker();
}
private static final Ticker SYSTEM_TICKER =
new Ticker() {
@Override
public long read() {
//ticker工具类read方法,直接获取机器的毫秒时间
return Platform.systemNanoTime();
}
};
static long systemNanoTime() {
return System.nanoTime();
}
StopWatch的几个关键方法:
public Stopwatch start() {
checkState(!isRunning, "This stopwatch is already running.");
isRunning = true;
startTick = ticker.read();//设置startTick时间为stopwatch开始启动的时刻时间
return this;
}
public Stopwatch stop() {
long tick = ticker.read();
checkState(isRunning, "This stopwatch is already stopped.");
isRunning = false;
//设置elapsedNanos时间为方法调用时间-stopwatch开启时间+上次程序stopwatch的elapsedNanos历史时间
elapsedNanos += tick - startTick;
return this;
}
public long elapsed(TimeUnit desiredUnit) {
return desiredUnit.convert(elapsedNanos(), NANOSECONDS);
}
private long elapsedNanos() {
//如果stopwatch仍在运行中,返回当前时刻时间-stopwatch开启时刻时间+历史elapsedNanos时间(elapsedNanos只在stop和reset时会更新)
//如果stopwatch已停止运行,则直接返回elapsedNanos,详见stop()
return isRunning ? ticker.read() - startTick + elapsedNanos : elapsedNanos;
}
结论
调用方式1:
Stopwatch stopwatch = Stopwatch.createStarted();
doSomething();
stopwatch.stop(); // optional
long millis = stopwatch.elapsed(MILLISECONDS);
log.info("time: " + stopwatch); // formatted string like "12.3 ms"
使用stopwatch对程序运行时间进行调试,首先调用StopWatch.createStarted()
创建并启动一个stopwatch实例,调用stopwatch.stop()停止计时,此时会更新stopwatch的elapsedNanos时间,为stopwatch开始启动到结束计时的时间,再次调用stopwatch.elapsed(),获取stopwatch在start-stop时间段,时间流逝的长度。
调用方式2:
Stopwatch stopwatch = Stopwatch.createStarted();
doSomething();
//stopwatch.stop();
long millis = stopwatch.elapsed(MILLISECONDS);
log.info("time: " + stopwatch); // formatted string like "12.3 ms"
createStarted启动了一个stopwatch实例,stopwatch的时间持续流逝,调用elapsed方法,返回isRunning ? ticker.read() - startTick + elapsedNanos : elapsedNanos;
,此时得到的返回值是当前时间和stopwatch.start()时刻时间的时间差值,所以是一个持续递增的时间。
如果需要在程序中对关键步骤的每一步进行进行持续度量,需要使用如下调用方式
Stopwatch stopwatch = Stopwatch.createStarted();
doSomething();
stopwatch.stop();
long millis = stopwatch.elapsed(MILLISECONDS);
log.info("time: " + stopwatch); // formatted string like "12.3 ms"
stopwatch.reset().start();
doSomething();
stopwatch.stop();
long millis = stopwatch.elapsed(MILLISECONDS);
log.info("time: " + stopwatch); // formatted string like "12.3 ms"