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

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


当前回答

我实现了一个简单的定时器,我认为它真的很有用:

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秒左右。因此,系统调用的时间。纳米时间等,也没有系统的准确性。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编译器完成它的工作,然后重复此测试多次,并使用最短的执行时间。

System.currentTimeMillis ();并不是衡量算法性能的好方法。它衡量的是你作为用户看电脑屏幕的总时间。它还包括在您的计算机上运行的所有其他事情所消耗的时间。如果您的工作站上运行了许多程序,这可能会产生巨大的不同。

正确的方法是使用java.lang.management包。

来自http://nadeausoftware.com/articles/2008/03/java_tip_how_get_cpu_and_user_time_benchmarking网站(档案链接):

“用户时间”是运行应用程序自己的代码所花费的时间。 “系统时间”是代表应用程序运行操作系统代码所花费的时间(例如用于I/O)。

getCpuTime()方法给出了它们的和:

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;

public class CPUUtils {

    /** Get CPU time in nanoseconds. */
    public static long getCpuTime( ) {
        ThreadMXBean bean = ManagementFactory.getThreadMXBean( );
        return bean.isCurrentThreadCpuTimeSupported( ) ?
            bean.getCurrentThreadCpuTime( ) : 0L;
    }

    /** Get user time in nanoseconds. */
    public static long getUserTime( ) {
        ThreadMXBean bean = ManagementFactory.getThreadMXBean( );
        return bean.isCurrentThreadCpuTimeSupported( ) ?
            bean.getCurrentThreadUserTime( ) : 0L;
    }

    /** Get system time in nanoseconds. */
    public static long getSystemTime( ) {
        ThreadMXBean bean = ManagementFactory.getThreadMXBean( );
        return bean.isCurrentThreadCpuTimeSupported( ) ?
            (bean.getCurrentThreadCpuTime( ) - bean.getCurrentThreadUserTime( )) : 0L;
    }

}

如果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);
        }
    }
}

这是一个简单的类用于简单的函数计时。下面有一个例子。

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

这可能不是您想让我说的,但是这是AOP的一个很好的用法。在您的方法周围使用代理拦截器,并在其中进行计时。

遗憾的是,AOP的什么、为什么和如何超出了这个答案的范围,但这就是我可能会做的事情。

编辑:如果你有兴趣的话,这里有一个Spring AOP的链接可以帮助你入门。这是Iive在java中遇到的最容易访问的AOP实现。

另外,考虑到其他人的简单建议,我应该补充一点:AOP适用于不希望时间之类的东西侵入代码的情况。但在很多情况下,这种简单易行的方法是可以的。