package org.nutz.lang;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 秒表
*
* @author zozoh(zozohtnt@gmail.com)
*/
public class Stopwatch {
private boolean nano;
private long from;
private long to;
private List<StopTag> tags;
private StopTag lastTag;
/**
* 秒表开始计时,计时时间的最小单位是毫秒
*
* @return 开始计时的秒表对象
*/
public static Stopwatch begin() {
Stopwatch sw = new Stopwatch();
sw.start();
return sw;
}
/**
* 秒表开始计时,计时时间的最小单位是毫微秒
*
* @return 开始计时的秒表对象
*/
public static Stopwatch beginNano() {
Stopwatch sw = new Stopwatch();
sw.nano = true;
sw.start();
return sw;
}
/**
* 创建一个秒表对象,该对象的计时时间的最小单位是毫秒
*
* @return 秒表对象
*/
public static Stopwatch create() {
return new Stopwatch();
}
/**
* 创建一个秒表对象,该对象的计时时间的最小单位是毫微秒
*
* @return 秒表对象
*/
public static Stopwatch createNano() {
Stopwatch sw = new Stopwatch();
sw.nano = true;
return sw;
}
public static Stopwatch run(Runnable atom) {
Stopwatch sw = begin();
atom.run();
sw.stop();
return sw;
}
public static Stopwatch runNano(Runnable atom) {
Stopwatch sw = beginNano();
atom.run();
sw.stop();
return sw;
}
/**
* 开始计时,并返回开始计时的时间,该时间最小单位由创建秒表时确定
*
* @return 开始计时的时间
*/
public long start() {
from = currentTime();
to = from;
return from;
}
private long currentTime() {
return nano ? System.nanoTime() : System.currentTimeMillis();
}
/**
* 记录停止时间,该时间最小单位由创建秒表时确定
*
* @return 自身以便链式赋值
*/
public long stop() {
to = currentTime();
return to;
}
/**
* @return 计时结果(ms)
*/
public long getDuration() {
return to - from;
}
/**
* @see #getDuration()
*/
public long du() {
return to - from;
}
/**
* 开始计时的时间,该时间最小单位由创建秒表时确定
*
* @return 开始计时的时间
*/
public long getStartTime() {
return from;
}
/**
* 停止计时的时间,该时间最小单位由创建秒表时确定
*
* @return 停止计时的时间
*/
public long getEndTime() {
return to;
}
/**
* 返回格式为 <code>Total: [计时时间][计时时间单位] : [计时开始时间]=>[计时结束时间]</code> 的字符串
*
* @return 格式为 <code>Total: [计时时间][计时时间单位] : [计时开始时间]=>[计时结束时间]</code> 的字符串
*/
@Override
public String toString() {
String prefix = String.format("Total: %d%s : [%s]=>[%s]",
this.getDuration(),
(nano ? "ns" : "ms"),
Times.sDTms(new Date(from)),
Times.sDTms(new Date(to)));
if (tags == null)
return prefix;
StringBuilder sb = new StringBuilder(prefix).append("\r\n");
for (int i = 0; i < tags.size(); i++) {
StopTag tag = tags.get(i);
sb.append(String.format(" -> %5s: %dms",
tag.name == null ? "TAG" + i : tag.name,
tag.du()));
if (i < tags.size() - 1)
sb.append("\r\n");
}
return sb.toString();
}
public StopTag tag(String name) {
if (tags == null)
tags = new ArrayList<Stopwatch.StopTag>();
lastTag = new StopTag(name, System.currentTimeMillis(), lastTag);
tags.add(lastTag);
return lastTag;
}
public StopTag tagf(String fmt, Object... args) {
return tag(String.format(fmt, args));
}
public class StopTag {
public String name;
public long tm;
public StopTag pre;
public StopTag() {}
public StopTag(String name, long tm, StopTag pre) {
super();
this.name = name;
this.tm = tm;
this.pre = pre;
}
public long du() {
if (pre == null)
return tm - from;
return tm - pre.tm;
}
}
}