如何在Java中计算方法的执行时间?

1018
  1. 如何获取方法的执行时间?
  2. 是否有一个Timer实用程序类来计算任务所需的时间等?

大多数在Google上搜索的结果都是关于调度线程和任务的定时器,这不是我想要的。


JAMon API是一个免费、简单、高性能、线程安全的Java API,允许开发人员轻松监控生产应用程序的性能和可扩展性。JAMon跟踪点击次数、执行时间(总计、平均值、最小值、最大值、标准偏差)等等。http://jamonapi.sourceforge.net/下载: http://sourceforge.net/project/showfiles.php?group_id=96550 - Mike Pone
2
你可能还想看看Apache Commons Lang StopWatch类。一个简单但实用的工具类。 - user101561
类似的问题:如何在Java中编写正确的微基准测试? - Basil Bourque
是的,StopWatch非常适合这个。 - Shubham Pandey
Java 8使用Instant类:https://dev59.com/InVC5IYBdhLWcg3wz0h9#30975902 - akhil_mittal
42个回答

8
new Timer(""){{
    // code to time 
}}.timeMe();



public class Timer {

    private final String timerName;
    private long started;

    public Timer(String timerName) {
        this.timerName = timerName;
        this.started = System.currentTimeMillis();
    }

    public void timeMe() {
        System.out.println(
        String.format("Execution of '%s' takes %dms.", 
                timerName, 
                started-System.currentTimeMillis()));
    }

}

1
编写自己的简单类是一个不错的选择,当你已经有了构建系统和依赖的 OTS 设置,并且不想麻烦地引入另一个包含实用计时器类的 OTS 包时。 - Ogre Psalm33

7

我基本上做的就是这个,但考虑到热点编译的工作原理,如果你想得到准确的结果,你需要放弃前面的几次测量,并确保你正在使用的方法在一个真实的世界(阅读应用特定)中。

如果JIT决定编译它,你的数字将会有很大变化。所以请注意。


7

有几种方法可以做到这一点。我通常会回退到使用类似于以下内容的东西:

long start = System.currentTimeMillis();
// ... do something ...
long end = System.currentTimeMillis();

或者使用System.nanoTime()来完成相同的事情。

对于更多基准测试方面的内容,似乎还有这个:http://jetm.void.fm/ 不过我从未尝试过。


6

如果您需要墙钟时间

long start_time = System.currentTimeMillis();
object.method();
long end_time = System.currentTimeMillis();
long execution_time = end_time - start_time;

5
正如"skaffman"所说,您可以使用AOP或者运行时字节码织入,就像单元测试方法覆盖工具使用的那样,透明地向调用的方法添加时间信息。
您可以查看开源工具Emma (http://downloads.sourceforge.net/emma/emma-2.0.5312-src.zip?modtime=1118607545&big_mirror=0)使用的代码。另一个开源覆盖率工具是http://prdownloads.sourceforge.net/cobertura/cobertura-1.9-src.zip?download
如果您最终成功实现了自己想要的功能,请通过您的ant任务/ jars与社区分享。

5
long startTime = System.currentTimeMillis();
// code goes here
long finishTime = System.currentTimeMillis();
long elapsedTime = finishTime - startTime; // elapsed time in milliseconds

4
在Java 8中引入了一个名为Instant的新类。根据文档:

Instant表示时间线上一纳秒的开始。此类用于生成时间戳以表示机器时间。即使需要存储比long更大的数字,瞬时的范围也无法承受。为了实现这一点,该类存储表示纪元秒和表示秒内纳秒的int的long,后者始终在0到999,999,999之间。从标准Java时代1970-01-01T00:00:00Z开始测量纪元秒,纪元之后的瞬时值为正值,而较早的瞬时值为负值。对于纪元秒和纳秒部分,较大的值始终比较小的值更靠近时间线。

可以使用以下方法:

Instant start = Instant.now();
try {
    Thread.sleep(7000);
} catch (InterruptedException e) {
    e.printStackTrace();
}
Instant end = Instant.now();
System.out.println(Duration.between(start, end));

它会打印出PT7.001S


4

好的,这是一个简单的类,用于对您的函数进行简单的定时。下面有一个示例。

public class Stopwatch {
    static long startTime;
    static long splitTime;
    static long endTime;

    public Stopwatch() {
        start();
    }

    public void start() {
        startTime = System.currentTimeMillis();
        splitTime = System.currentTimeMillis();
        endTime = System.currentTimeMillis();
    }

    public void split() {
        split("");
    }

    public void split(String tag) {
        endTime = System.currentTimeMillis();
        System.out.println("Split time for [" + tag + "]: " + (endTime - splitTime) + " ms");
        splitTime = endTime;
    }

    public void end() {
        end("");
    }
    public void end(String tag) {
        endTime = System.currentTimeMillis();
        System.out.println("Final time for [" + tag + "]: " + (endTime - startTime) + " ms");
    }
}

使用示例:

public static Schedule getSchedule(Activity activity_context) {
        String scheduleJson = null;
        Schedule schedule = null;
/*->*/  Stopwatch stopwatch = new Stopwatch();

        InputStream scheduleJsonInputStream = activity_context.getResources().openRawResource(R.raw.skating_times);
/*->*/  stopwatch.split("open raw resource");

        scheduleJson = FileToString.convertStreamToString(scheduleJsonInputStream);
/*->*/  stopwatch.split("file to string");

        schedule = new Gson().fromJson(scheduleJson, Schedule.class);
/*->*/  stopwatch.split("parse Json");
/*->*/  stopwatch.end("Method getSchedule"); 
    return schedule;
}

控制台输出示例:

Split time for [file to string]: 672 ms
Split time for [parse Json]: 893 ms
Final time for [get Schedule]: 1565 ms

4

我的机器性能测试结果

  • System.nanoTime() : 750纳秒
  • System.currentTimeMillis() : 18纳秒

如前所述,System.nanoTime() 被认为是用来测量经过的时间。但要注意在循环等内部使用时的成本。


4
您可以使用Spring Core项目中的Stopwatch类:
代码:
StopWatch stopWatch = new StopWatch()
stopWatch.start();  //start stopwatch
// write your function or line of code.
stopWatch.stop();  //stop stopwatch
stopWatch.getTotalTimeMillis() ; ///get total time

Stopwatch文档: 简单的秒表,可以计时多个任务,显示总运行时间和命名任务的运行时间。隐藏了System.currentTimeMillis()的使用,提高了应用程序代码的可读性并降低了计算错误的可能性。 请注意,该对象不是为线程安全而设计的,也不使用同步。该类通常用于在概念验证和开发过程中验证性能,而不是作为生产应用程序的一部分。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接