如何在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个回答

4

我修改了正确答案的代码以在几秒钟内获得结果:

long startTime = System.nanoTime();

methodCode ...

long endTime = System.nanoTime();
double duration = (double)(endTime - startTime) / (Math.pow(10, 9));
Log.v(TAG, "MethodName time (s) = " + duration);

3

如果只想要知道时间,可以尝试以下方法。

long startTime = System.currentTimeMillis();
//@ Method call
System.out.println("Total time [ms]: " + (System.currentTimeMillis() - startTime));    

2

如果Java拥有更好的函数支持将会很不错,这样需要测量的操作就可以被包装成一个块:

measure {
   // your operation here
}

在Java中,可以通过匿名函数来实现此操作,但这种方式过于冗长。
public interface Timer {
    void wrap();
}


public class Logger {

    public static void logTime(Timer timer) {
        long start = System.currentTimeMillis();
        timer.wrap();
        System.out.println("" + (System.currentTimeMillis() - start) + "ms");
    }

    public static void main(String a[]) {
        Logger.logTime(new Timer() {
            public void wrap() {
                // Your method here
                timeConsumingOperation();
            }
        });

    }

    public static void timeConsumingOperation() {
        for (int i = 0; i<=10000; i++) {
           System.out.println("i=" +i);
        }
    }
}

1
可能可以通过使用Java 8的lambda表达式来进行清理。http://www.drdobbs.com/jvm/lambda-expressions-in-java-8/240166764?pgno=2 - Ogre Psalm33
自Java 8以来,java.lang.Runnable是一个@FunctionalInterface,这意味着您可以将lambda表达式传递给任何以Runnable作为参数的方法。您的timeThisCode(Runnable r)可以简单地返回毫秒/纳秒或更详细的经过时间表示。 - Cornel Masson

2
你可以使用javaagent来动态地修改Java类字节码并添加监控代码。在GitHub上有一些开源工具可以为您完成此操作。
如果您想自己实现,请实现javaagent,使用javassist修改您想要监视的方法,并在方法返回之前添加监视代码。这是一种干净的方式,您可以监视甚至没有源代码的系统。

2

这里是格式化后的字符串,显示已经过去的时间,类似于谷歌搜索所需的时间:

        long startTime = System.nanoTime();
        //  ... methodToTime();
        long endTime = System.nanoTime();
        long duration = (endTime - startTime);
        long seconds = (duration / 1000) % 60;
        // formatedSeconds = (0.xy seconds)
        String formatedSeconds = String.format("(0.%d seconds)", seconds);
        System.out.println("formatedSeconds = "+ formatedSeconds);
        // i.e actual formatedSeconds = (0.52 seconds)

nonoTime不是/1000秒。你的数学假设了毫秒。最好使用/1e6来获取毫秒。 - simbo1905

2

我实现了一个简单的计时器,我认为它非常有用:

public class Timer{
    private static long start_time;

    public static double tic(){
        return start_time = System.nanoTime();
    }

    public static double toc(){
        return (System.nanoTime()-start_time)/1000000000.0;
    }

}

这样您就可以计时一个或多个操作:

Timer.tic();
// Code 1
System.out.println("Code 1 runtime: "+Timer.toc()+" seconds.");
// Code 2
System.out.println("(Code 1 + Code 2) runtime: "+Timer.toc()+"seconds");
Timer.tic();
// Code 3
System.out.println("Code 3 runtime: "+Timer.toc()+" seconds.");

1
我在Java EE中使用的一种有效策略是:

  1. Create a class with a method annotated with @AroundInvoke;

    @Singleton
    public class TimedInterceptor implements Serializable {
    
        @AroundInvoke
        public Object logMethod(InvocationContext ic) throws Exception {
            Date start = new Date();
            Object result = ic.proceed();
            Date end = new Date();
            System.out.println("time: " + (end.getTime - start.getTime()));
            return result;
        }
    }
    
  2. Annotate the method that you want to monitoring:

    @Interceptors(TimedInterceptor.class)
    public void onMessage(final Message message) { ... 
    
我希望这可以帮助到您。

1

System.nanoTime() 是一个非常精确的系统工具,用于测量执行时间。但是要小心,如果您正在运行抢占式调度模式(默认情况下),此实用程序实际上会测量墙钟时间而不是 CPU 时间。因此,您可能会注意到不同的执行时间值从运行到运行,这取决于系统负载。如果您正在寻找 CPU 时间,我认为在实时模式下运行程序会有所帮助。您必须使用 RT Linux。链接:Linux 实时编程


1
对于Java 8+,另一个可能的解决方案(更加通用、函数式且无需使用Aspect)是创建一些接受代码作为参数的实用方法。
public static <T> T timed (String description, Consumer<String> out, Supplier<T> code) {
    final LocalDateTime start = LocalDateTime.now ();
    T res = code.get ();
    final long execTime = Duration.between (start, LocalDateTime.now ()).toMillis ();
    out.accept (String.format ("%s: %d ms", description, execTime));
    return res;
}

而调用代码可能是这样的:

public static void main (String[] args) throws InterruptedException {
    timed ("Simple example", System.out::println, Timing::myCode);
}

public static Object myCode () {
    try {
        Thread.sleep (1500);
    } catch (InterruptedException e) {
        e.printStackTrace ();
    }
    return null;
}

0

还可以实现Timer接口并在您的类的任何方法上执行

import java.util.function.*;

public interface Timer {

    default void timeIt(Runnable r) {
        timeIt(() -> { r.run(); return 0;});
    }

    default <S,T> T timeIt(Function<S,T> fun, S arg) {
        long start = System.nanoTime();
        T result = fun.apply(arg);
        long stop = System.nanoTime();
        System.out.println("Time: " + (stop-start)/1000000.0 + " msec");
        return result;
    }

    default <T> T timeIt(Supplier<T> s) {
        return timeIt(obj -> s.get(), null);
    }
}

使用方法:

class MyClass implements Timer ..

timeIt(this::myFunction); 

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