前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >优雅的实现程序计时器

优雅的实现程序计时器

作者头像
呼延十
发布2019-07-01 17:11:42
8140
发布2019-07-01 17:11:42
举报
文章被收录于专栏:呼延呼延

日常编码中,如果想对某一段程序计时,应该怎么做呢?比较简单粗暴的办法就是开始和结束各自取当前时间戳.

代码语言:javascript
复制
        long start = System.currentTimeMillis();
        dosomething();
        System.out.println("做了一些事情:" + (System.currentTimeMillis() - start));

其实看起来还好对不对,我偶尔这么用一下也觉得还好,知道某一次维护某一份代码.

前任因为需要对程序的性能做一些优化,所以要找到程序耗时较高的部分,所以几个主要的类里面到处是这种代码,在他进行优化完毕之后并没有进行删除.

而我当时程序已经运行良好了,需要进行代码clean(因为实在是太丑了),一个个删除实在是累skr人.

而且long start = System.currentTimeMillis();这一句实在是不好找,因为他没有引用别的参数,所以并不会有编译器来提醒我哪里还有遗漏的,导致在那之后好久都会偶尔又找到一条呢!

而我在日常写一些奇怪的类的时候,也有打印耗时的需求,比如我前面一些博客里面,说怎么操作优化了效率,总不能空口白话,因此也需要经常的打印程序耗时.我感觉到上面的这种粗暴的办法太傻了,但是也没想到什么好办法,知道看到了Ticker类.

这个类的实现功能是,可以对程序分段计时并标注,并且将代码封装起来,尽量少的侵入业务代码,同时最后以较好的可读性打印出来.

实现方法,维护一个<string,long>的list,注意前面这么写只是代表了一个对象,而不是一个Map.用户每次手动调用计时的时候,计算与前一次计时之间的间隔时间,将其保存起来,同时,Ticker保存初始化的时间,以及最终调用toString的时间,因此你可以很清楚的看到一个类似于:

代码语言:javascript
复制
thing1: 10ms
thing2: 20ms
total: 30ms

这样子的输出.

下面是类的代码以及使用示例:

代码语言:javascript
复制
package util;

import java.util.ArrayList;
import java.util.List;

public class Ticker {

    private final List<T> tags = new ArrayList<>(2);

    private final long start;
    private long last;
    private long end;

    public Ticker() {
        start = System.currentTimeMillis();
        last = start;
    }

    public void tack() {
        last = System.currentTimeMillis();
    }

    public void tick(String tag) {
        long now = System.currentTimeMillis();
        tags.add(new T(tag, (int) (now - last)));
        last = now;
    }

    public int total() {
        if (end == 0)
            end = System.currentTimeMillis();
        return (int) (end - start);
    }

    public long getBegin() {
        return start;
    }

    @Override
    public String toString() {
        return summary();
    }

    private String summary() {
        end = System.currentTimeMillis();
        StringBuilder sb = new StringBuilder(32);
        for (T tag : tags) {
            sb.append(tag.tag).append(" ").append(tag.since).append("ms, ");
        }

        sb.append("total ");
        if ((end - start) < 10000) {
            sb.append(end - start).append("ms");
        } else {
            sb.append((end - start) / 1000).append("s");
        }
        return sb.toString();
    }

    static class T {
        final String tag;
        final int since;

        T(String tag, int since) {
            this.tag = tag;
            this.since = since;
        }
    }

    private static void db() throws InterruptedException {
        Thread.sleep(1000);
    }

    private static void col() {
        for (int i = 0; i < 10000; ++i) {
            int j = i;
        }
    }


    public static void main(String[] args) throws InterruptedException {
        Ticker ticker = new Ticker();
        db();
        ticker.tick("db");
        col();
        ticker.tick("col");
        System.out.println(ticker.toString());
    }
}

main方法中的测试代码输出:

代码语言:javascript
复制
db 1005ms, col 1ms, total 1006ms

是不是感觉好很多了呢.

完全没有什么依赖,没有什么副作用,copy到项目里就能用,眼睛舒服了许多.

完。

ChangeLog

2019-04-28 完成

以上皆为个人所思所得,如有错误欢迎评论区指正。

欢迎转载,烦请署名并保留原文链接。

联系邮箱:huyanshi2580@gmail.com


本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ChangeLog
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档