001package net.gdface.utils;
002
003import java.util.concurrent.TimeUnit;
004import java.util.concurrent.atomic.AtomicLong;
005
006/**
007 *  耗时统计对象<br>
008 *  用于程序执行耗时统计
009 * @author guyadong
010 *
011 */
012public class TimeCostProbe{
013        /**
014         * 统计时间(毫秒)
015         */
016        private AtomicLong timeCostMills=new AtomicLong(0);
017        /**
018         * 统计次数
019         */
020        private AtomicLong count=new AtomicLong(0);
021        /**
022         * 统计位置
023         */
024        private String location=null ;
025        /**
026         * 默认输入的时间单位
027         */
028        private TimeUnit outTimeUnit = TimeUnit.SECONDS;
029        /**
030         * 获取当前方法名
031         * @return
032         */
033        private String getMethodName(){
034                StackTraceElement stack = Thread.currentThread().getStackTrace()[3];
035                return stack.getClassName()+"."+stack.getMethodName();
036        }
037        /**
038         * 计时开始
039         * @return
040         */
041        public TimeCostProbe begin() {
042                location=getMethodName();
043                timeCostMills.set(System.currentTimeMillis());
044                return this;
045        }
046        /**
047         * 计时结束
048         * @return
049         */
050        public TimeCostProbe end(){
051                if(0==timeCostMills.get())
052                        throw new IllegalArgumentException("begin/end not match");
053                if(!getMethodName().equals(location))
054                        throw new IllegalArgumentException("begin/end must be call in same method");
055                timeCostMills.set(System.currentTimeMillis()-timeCostMills.get());
056                if(count.get() ==0){
057                        count.set(1);
058                }
059                return this;
060        }               
061        /**
062         * 计时结果相加
063         * @param mills
064         * @return
065         */
066        public TimeCostProbe add(long mills){                   
067                timeCostMills.addAndGet(mills);
068                count.incrementAndGet();
069                return this;
070        }
071        public TimeCostProbe addCount(){                        
072                count.incrementAndGet();
073                return this;
074        }
075        public long getTimeCostMills() {
076                return timeCostMills.get();
077        }
078        public long getTimeCost(TimeUnit unit) {
079                return unit.convert(timeCostMills.get(), TimeUnit.MICROSECONDS);
080        }
081        /**
082         * 向输出设备打印耗时统计信息
083         * @see #log(String)
084         */
085        public void print(){
086                System.out.println(log(location));
087        }
088        /**
089         * 输出耗时统计信息
090         * @param name
091         * @return
092         */
093        public String log(String name){
094                return log(name,outTimeUnit);
095        }
096        /**
097         * 以unit为时间单位输出统计信息
098         * @param name
099         * @param unit
100         * @return
101         */
102        public String log(String name,TimeUnit unit){
103                if(0==count.get())
104                        throw new IllegalArgumentException("begin/end not match");
105                return String.format("%s: average cost:%f %s(sample count %d)\n",name,
106                                unit.convert(timeCostMills.get(), TimeUnit.MILLISECONDS)/(double)count.get(),
107                                unit.name().toLowerCase(),
108                                count.get());
109        }
110        public String log(){
111                return log(location);
112        }
113        public TimeUnit getOutTimeUnit() {
114                return outTimeUnit;
115        }
116        /**
117         * 设置输出时间单位
118         * @param outTimeUnit
119         * @return
120         */
121        public TimeCostProbe setOutTimeUnit(TimeUnit outTimeUnit) {
122                if(null != outTimeUnit){
123                        this.outTimeUnit = outTimeUnit;
124                }
125                return this;
126        }
127}