如何获得方法的执行时间? 是否有Timer实用程序类来计时任务所需的时间等?

在谷歌上的大多数搜索都返回调度线程和任务的计时器的结果,这不是我想要的。


当前回答

这里有很多有效的答案,它们都是在方法中实现的。为了制作一个通用的计时方法,我通常有一个timing类,它由以下内容组成。

public record TimedResult<T>(T result, Duration duration) {}

public static Duration time(Runnable r) {
    var s = Instant.now();
    r.run();
    var dur = Duration.between(s, Instant.now());
    return dur;
}

public static <T> TimedResult<T> time(Callable<T> r) throws Exception {
    var s = Instant.now();
    T res = r.call();
    var dur = Duration.between(s, Instant.now());
    return new TimedResult<>(res, dur);
}

这足够通用,可以传递Runnable或Callable对象。

Duration result = Timing.time(() -> {
    // do some work.
});

TimedResult<String> result = Timing.time(() -> {
    // do some work.
    return "answer";
});

Duration timeTaken = result.duration();
String answer = result.result();

其他回答

使用分析器(JProfiler, Netbeans profiler, Visual VM, Eclipse profiler等)。您将得到最准确的结果,并且是最少的干扰。它们使用内置的JVM机制进行概要分析,还可以为您提供额外的信息,如堆栈跟踪、执行路径以及必要时更全面的结果。

当使用完全集成的分析器时,对方法进行分析是非常简单的。右击,分析器->添加到根方法。然后像运行测试运行或调试器一样运行剖析器。

正如“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 task/jars与社区分享。

如果您不使用工具,并且希望对执行时间较短的方法进行计时,那么只需执行多次,每次将执行次数增加一倍,直到达到1秒左右。因此,系统调用的时间。纳米时间等,也没有系统的准确性。nanoTime确实对结果有很大影响。

    int runs = 0, runsPerRound = 10;
    long begin = System.nanoTime(), end;
    do {
        for (int i=0; i<runsPerRound; ++i) timedMethod();
        end = System.nanoTime();
        runs += runsPerRound;
        runsPerRound *= 2;
    } while (runs < Integer.MAX_VALUE / 2 && 1000000000L > end - begin);
    System.out.println("Time for timedMethod() is " + 
        0.000000001 * (end-begin) / runs + " seconds");

当然,使用挂钟也有一些注意事项:jit编译、多线程/进程等的影响。因此,您需要首先执行该方法很多次,以便JIT编译器完成它的工作,然后重复此测试多次,并使用最短的执行时间。

可以使用javaagent修改java类字节,动态添加监控代码。github上有一些开源工具可以帮你做到这一点。 如果您想自己完成,只需实现javaagent,使用javassist修改要监视的方法,并在方法返回之前修改监视代码。它很干净,你甚至可以监视没有源代码的系统。

Spring提供了一个实用工具类org.springframework.util。秒表,根据JavaDoc:

简单的秒表,允许计时多项任务,暴露 每个指定任务的总运行时间和运行时间。

用法:

StopWatch stopWatch = new StopWatch("Performance Test Result");

stopWatch.start("Method 1");
doSomething1();//method to test
stopWatch.stop();

stopWatch.start("Method 2");
doSomething2();//method to test
stopWatch.stop();

System.out.println(stopWatch.prettyPrint());

输出:

StopWatch 'Performance Test Result': running time (millis) = 12829
-----------------------------------------
ms     %     Task name
-----------------------------------------
11907  036%  Method 1
00922  064%  Method 2

方面:

@Around("execution(* my.package..*.*(..))")
public Object logTime(ProceedingJoinPoint joinPoint) throws Throwable {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    Object retVal = joinPoint.proceed();
    stopWatch.stop();
    log.info(" execution time: " + stopWatch.getTotalTimeMillis() + " ms");
    return retVal;
}