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


834
  1. 如何获得方法的执行时间?
  2. 是否有Timer实用程序类来处理诸如计时任务花费多长时间等问题?

Google上的大多数搜索都会返回安排线程和任务的计时器的结果,这不是我想要的。


JAMon API是一种免费,简单,高性能,线程安全的Java API,使开发人员可以轻松监视生产应用程序的性能和可伸缩性。JAMon跟踪命中,执行时间(总计,平均,最小,最大,标准开发)等。http://jamonapi.sourceforge.net/下载:http
group_id=96550

1
您可能还想看看Apache Commons Lang StopWatch类。一个简单但有用的实用程序类。


是的,秒表非常适合此操作。
Shubham Pandey

Answers:


1207

总有一种老式的方式:

long startTime = System.nanoTime();
methodToTime();
long endTime = System.nanoTime();

long duration = (endTime - startTime);  //divide by 1000000 to get milliseconds.

233
实际上,它是“新式的”,因为您使用了nanoTime,直到java5才添加了nanoTime
John Gardner

11
这(或使用System.currentTimeMillis())似乎是它通常在Java中完成的方式……无论如何我都已经看到了。仍然让我感到有些惊讶的是,没有漂亮的内置类,例如Timer t = new Timer();。字符串s = t.getElapsed(format); 等等...
Ogre Psalm33

18
尽管通常可以,但是nanoTime不能保证其精度优于currentTimeMillis()。forums.sun.com/thread.jspa?messageID=9460663simongbrown.com/blog/2007/08/20/...
詹姆斯Schek

10
当然,记住微基准测试的陷阱总是很重要的,例如可能会使结果失真的编译器/ JVM优化= 8
Yuval,2009年

18
不需要final块,因为如果引发异常,则不会使用endTime。
彼得·劳瑞

197

我接受简单的答案。为我工作。

long startTime = System.currentTimeMillis();

doReallyLongThing();

long endTime = System.currentTimeMillis();

System.out.println("That took " + (endTime - startTime) + " milliseconds");

效果很好。分辨率显然只有毫秒,您可以使用System.nanoTime()做得更好。两者都有一些限制(操作系统调度片等),但是效果很好。

在几次运行中取平均值(越多越好),您将得到一个不错的主意。


51
实际上,System.currentTimeMillis()仅在15ms以上才是准确的。对于非常低的值,它是不可信的。解决方案(如上所述)是System.nanoTime();。
史蒂夫·克

好的,在我读完史蒂夫·克的评论之前,我将接受它作为正式答案。好消息,史蒂夫!
Ogre Psalm33

4
nanoTime()不能保证比currentTimeMillis更好的精度,但是许多JVM实现的确具有更好的nanoTime精度。
詹姆斯·谢克

5
@JamesSchek您确实需要注意自己的措辞,正如我在其他地方已经提到的相同评论一样;nanoTime保证至少currentTimeMillisdocs.oracle.com/javase/7/docs/api/java/lang/...
b1nary.atr0phy

的一个小好处currentTimeMillis是它是一个实际的时间戳,也可以用于记录开始/结束时间,而nanoTime“只能用于测量经过的时间,并且与系统或挂钟时间的任何其他概念均无关。”
布莱德·帕克斯

177

拜托了伙计们!没有人提到使用番石榴的方法(可以说真棒):

import com.google.common.base.Stopwatch;

Stopwatch timer = Stopwatch.createStarted();
//method invocation
LOG.info("Method took: " + timer.stop());

令人高兴的是,Stopwatch.toString()在选择测量时间单位方面做得很好。即,如果值较小,则将输出38 ns,如果值较长,则将显示5m 3s

更好:

Stopwatch timer = Stopwatch.createUnstarted();
for (...) {
   timer.start();
   methodToTrackTimeFor();
   timer.stop();
   methodNotToTrackTimeFor();
}
LOG.info("Method took: " + timer);

注意:Google Guava需要Java 1.6+


21
不幸的是,番石榴的秒表不是线程安全的。我经过惨痛的教训才学到这个。
Dexter Legaspi 2014年

6
@DexterLegaspi对您的经历会非常感兴趣!想要分享?
Siddhartha 2015年

1
并行使用秒表将导致您start()连续调用多次(与相同stop())。
Mingwei Samuel

141

使用Java 8新API中的InstantDuration

Instant start = Instant.now();
Thread.sleep(5000);
Instant end = Instant.now();
System.out.println(Duration.between(start, end));

输出,

PT5S

2
谢谢,如何在没有PT的情况下输出结果?
java123999 '16

1
方法的问题在于,Instant不会影响毫微秒和纳秒精度。参考:stackoverflow.com/questions/20689055/…–
prashantsunkari

8
@ java123999:您可以致电Duration.between(start, end).getSeconds()Duration还具有转换为其他时间单位的方法,例如toMillis()转换为毫秒。
埃米尔·隆德'18

100

将所有可能的方式集中到一个地方。

日期

Date startDate = Calendar.getInstance().getTime();
long d_StartTime = new Date().getTime();
Thread.sleep(1000 * 4);
Date endDate = Calendar.getInstance().getTime();
long d_endTime = new Date().getTime();
System.out.format("StartDate : %s, EndDate : %s \n", startDate, endDate);
System.out.format("Milli = %s, ( D_Start : %s, D_End : %s ) \n", (d_endTime - d_StartTime),d_StartTime, d_endTime);

系统。currentTimeMillis()

long startTime = System.currentTimeMillis();
Thread.sleep(1000 * 4);
long endTime = System.currentTimeMillis();
long duration = (endTime - startTime);  
System.out.format("Milli = %s, ( S_Start : %s, S_End : %s ) \n", duration, startTime, endTime );
System.out.println("Human-Readable format : "+millisToShortDHMS( duration ) );

可读格式

public static String millisToShortDHMS(long duration) {
    String res = "";    // java.util.concurrent.TimeUnit;
    long days       = TimeUnit.MILLISECONDS.toDays(duration);
    long hours      = TimeUnit.MILLISECONDS.toHours(duration) -
                      TimeUnit.DAYS.toHours(TimeUnit.MILLISECONDS.toDays(duration));
    long minutes    = TimeUnit.MILLISECONDS.toMinutes(duration) -
                      TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(duration));
    long seconds    = TimeUnit.MILLISECONDS.toSeconds(duration) -
                      TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration));
    long millis     = TimeUnit.MILLISECONDS.toMillis(duration) - 
                      TimeUnit.SECONDS.toMillis(TimeUnit.MILLISECONDS.toSeconds(duration));

    if (days == 0)      res = String.format("%02d:%02d:%02d.%04d", hours, minutes, seconds, millis);
    else                res = String.format("%dd %02d:%02d:%02d.%04d", days, hours, minutes, seconds, millis);
    return res;
}

番石榴:Google 秒表JAR « 秒表的目的是测量经过的时间(以纳秒为单位)。

com.google.common.base.Stopwatch g_SW = Stopwatch.createUnstarted();
g_SW.start();
Thread.sleep(1000 * 4);
g_SW.stop();
System.out.println("Google StopWatch  : "+g_SW);

Apache Commons Lang JAR « StopWatch提供了方便的计时API。

org.apache.commons.lang3.time.StopWatch sw = new StopWatch();
sw.start();     
Thread.sleep(1000 * 4);     
sw.stop();
System.out.println("Apache StopWatch  : "+ millisToShortDHMS(sw.getTime()) );

乔达-时间

public static void jodaTime() throws InterruptedException, ParseException{
    java.text.SimpleDateFormat ms_SDF = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");
    String start = ms_SDF.format( new Date() ); // java.util.Date

    Thread.sleep(10000);

    String end = ms_SDF.format( new Date() );       
    System.out.println("Start:"+start+"\t Stop:"+end);

    Date date_1 = ms_SDF.parse(start);
    Date date_2 = ms_SDF.parse(end);        
    Interval interval = new org.joda.time.Interval( date_1.getTime(), date_2.getTime() );
    Period period = interval.toPeriod(); //org.joda.time.Period

    System.out.format("%dY/%dM/%dD, %02d:%02d:%02d.%04d \n", 
        period.getYears(), period.getMonths(), period.getDays(),
        period.getHours(), period.getMinutes(), period.getSeconds(), period.getMillis());
}

Java 8中的Java日期时间API « Duration对象代表两个Instant对象之间的时间段。

Instant start = java.time.Instant.now();
    Thread.sleep(1000);
Instant end = java.time.Instant.now();
Duration between = java.time.Duration.between(start, end);
System.out.println( between ); // PT1.001S
System.out.format("%dD, %02d:%02d:%02d.%04d \n", between.toDays(),
        between.toHours(), between.toMinutes(), between.getSeconds(), between.toMillis()); // 0D, 00:00:01.1001 

Spring Framework提供了 StopWatch实用程序类,以测量Java中的经过时间。

StopWatch sw = new org.springframework.util.StopWatch();
sw.start("Method-1"); // Start a named task
    Thread.sleep(500);
sw.stop();

sw.start("Method-2");
    Thread.sleep(300);
sw.stop();

sw.start("Method-3");
    Thread.sleep(200);
sw.stop();

System.out.println("Total time in milliseconds for all tasks :\n"+sw.getTotalTimeMillis());
System.out.println("Table describing all tasks performed :\n"+sw.prettyPrint());

System.out.format("Time taken by the last task : [%s]:[%d]", 
        sw.getLastTaskName(),sw.getLastTaskTimeMillis());

System.out.println("\n Array of the data for tasks performed « Task Name: Time Taken");
TaskInfo[] listofTasks = sw.getTaskInfo();
for (TaskInfo task : listofTasks) {
    System.out.format("[%s]:[%d]\n", 
            task.getTaskName(), task.getTimeMillis());
}

输出:

Total time in milliseconds for all tasks :
999
Table describing all tasks performed :
StopWatch '': running time (millis) = 999
-----------------------------------------
ms     %     Task name
-----------------------------------------
00500  050%  Method-1
00299  030%  Method-2
00200  020%  Method-3

Time taken by the last task : [Method-3]:[200]
 Array of the data for tasks performed « Task Name: Time Taken
[Method-1]:[500]
[Method-2]:[299]
[Method-3]:[200]

Guava的秒表,Apache Commons和Spring Framework都不是线程安全的。生产使用不安全。
Deepak Puthraya

@DeepakPuthraya那么使用哪个库对生产使用安全?
gaurav

1
@DeepakPuthraya可以使用Java 8提供的Java日期时间API。这很简单。
Yash

如果每个解决方案还可以显示系统输出的结果,则该职位将使IMO受益。
BAERUS

87

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

使用完全集成的探查器时,对方法进行探查是不容易的。右键单击Profiler->添加到根方法。然后像运行测试或调试器一样运行分析器。


这也是一个很好的建议,当我阅读此答案时,这对我来说就是“嘟嘟”的灯泡时刻之一。我们的项目使用的是JDeveloper,但是我检查了一下,当然,它有一个内置的探查器!
Ogre Psalm33

2
从Java 7 build 40(我认为)开始,他们包括了以前的JRockits Flight Recorder到Java(搜索Java Mission Control)
Niels Bech Nielsen 2014年


例如,如何通过Visual VM在Java中获取方法的执行?
okwap 2014年

41

这可能不是您要我说的,但这是对AOP的很好使用。在您的方法周围鞭打一个代理拦截器,并在那里计时。

遗憾的是,AOP的内容,原因和方式超出了此答案的范围,但这就是我可能要做的方式。

编辑:如果您热衷,这是一个到Spring AOP 的链接,可以帮助您入门。这是Iive为Java遇到的最易于访问的AOP实现。

同样,鉴于其他人的建议很简单,我应该补充一点,AOP适用于您不希望出现诸如定时入侵代码之类的事情的情况。但是在许多情况下,这种简单的方法很好。


3
这是有关如何使用Spring的教程:veerasundar.com/blog/2010/01/…–
David Tinker,

39

System.currentTimeMillis();这不是衡量算法性能的好方法。它衡量的是用户观看计算机屏幕时的总时间。它还包括后台在计算机上运行的所有其他设备所消耗的时间。如果您的工作站上有很多程序在运行,这可能会产生很大的不同。

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

http://nadeausoftware.com/articles/2008/03/java_tip_how_get_cpu_and_user_time_benchmarking网站:

  • “用户时间”是运行应用程序自己的代码所花费的时间。
  • “系统时间”是代表您的应用程序运行OS代码所花费的时间(例如,用于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;
    }

}

4
绝对好点是,“用户时间”(挂钟时间)并不总是衡量性能的好方法,尤其是在多线程程序中。
Ogre Psalm33 2014年

这是我正在寻找的答案。
赵刚

30

使用Java 8,您还可以使用所有常规方法执行以下操作

Object returnValue = TimeIt.printTime(() -> methodeWithReturnValue());
//do stuff with your returnValue

与TimeIt一样:

public class TimeIt {

public static <T> T printTime(Callable<T> task) {
    T call = null;
    try {
        long startTime = System.currentTimeMillis();
        call = task.call();
        System.out.print((System.currentTimeMillis() - startTime) / 1000d + "s");
    } catch (Exception e) {
        //...
    }
    return call;
}
}

使用这种方法,您可以轻松地在代码中的任何地方进行时间测量而不会中断代码。在这个简单的例子中,我只是打印时间。可以为TimeIt添加一个Switch,例如,仅以DebugMode或其他方式打印时间。

如果您正在使用Function,则可以执行以下操作:

Function<Integer, Integer> yourFunction= (n) -> {
        return IntStream.range(0, n).reduce(0, (a, b) -> a + b);
    };

Integer returnValue = TimeIt.printTime2(yourFunction).apply(10000);
//do stuff with your returnValue

public static <T, R> Function<T, R> printTime2(Function<T, R> task) {
    return (t) -> {
        long startTime = System.currentTimeMillis();
        R apply = task.apply(t);
        System.out.print((System.currentTimeMillis() - startTime) / 1000d
                + "s");
        return apply;
    };
}

这看起来比其他解决方案要好得多。它更接近Spring AOP,但比它轻。真Java 8方式!+1谢谢!
阿米特·库玛

也许这对您来说看起来不错,因为Stefan正在使用新的Java函数。但是我认为这很难读懂。
斯廷普森猫,

18

我们也可以使用Apache Commons的StopWatch类来测量时间。

样例代码

org.apache.commons.lang.time.StopWatch sw = new org.apache.commons.lang.time.StopWatch();

System.out.println("getEventFilterTreeData :: Start Time : " + sw.getTime());
sw.start();

// Method execution code

sw.stop();
System.out.println("getEventFilterTreeData :: End Time : " + sw.getTime());

15

如果您不使用工具并且想计时执行时间短的方法,请稍作调整:多次执行,每次执行次数加倍,直到达到一秒钟左右。因此,调用System.nanoTime的时间等等,也不会影响System.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编译器的工作,然后多次重复此测试,并花费最少的执行时间。


13

为此,我们正在使用AspectJ和Java批注。如果我们需要知道方法的执行时间,则可以简单地对其进行注释。更高级的版本可以使用自己的日志级别,该级别可以在运行时启用和禁用。

public @interface Trace {
  boolean showParameters();
}

@Aspect
public class TraceAspect {
  [...]
  @Around("tracePointcut() && @annotation(trace) && !within(TraceAspect)")
  public Object traceAdvice ( ProceedingJintPoint jP, Trace trace ) {

    Object result;
    // initilize timer

    try { 
      result = jp.procced();
    } finally { 
      // calculate execution time 
    }

    return result;
  }
  [...]
}


11

真的很好的代码。

http://www.rgagnon.com/javadetails/java-0585.html

import java.util.concurrent.TimeUnit;

long startTime = System.currentTimeMillis();
........
........
........
long finishTime = System.currentTimeMillis();

String diff = millisToShortDHMS(finishTime - startTime);


  /**
   * converts time (in milliseconds) to human-readable format
   *  "<dd:>hh:mm:ss"
   */
  public static String millisToShortDHMS(long duration) {
    String res = "";
    long days  = TimeUnit.MILLISECONDS.toDays(duration);
    long hours = TimeUnit.MILLISECONDS.toHours(duration)
                   - TimeUnit.DAYS.toHours(TimeUnit.MILLISECONDS.toDays(duration));
    long minutes = TimeUnit.MILLISECONDS.toMinutes(duration)
                     - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(duration));
    long seconds = TimeUnit.MILLISECONDS.toSeconds(duration)
                   - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration));
    if (days == 0) {
      res = String.format("%02d:%02d:%02d", hours, minutes, seconds);
    }
    else {
      res = String.format("%dd%02d:%02d:%02d", days, hours, minutes, seconds);
    }
    return res;
  }

3
实际上,问题是如何计算方法花费的时间,而不是如何格式化它。但是,这个问题已经很久了(将近四年!)。尝试避免重新使用旧线程,除非响应将在现有响应之上添加新的重要内容。
Leigh 2012年

1
并在末尾添加剩余的毫秒,请进行以下更改:long millis = TimeUnit.MILLISECONDS.toMillis(duration) - TimeUnit.SECONDS.toMillis(TimeUnit.MILLISECONDS.toSeconds(duration)); if (days == 0) { res = String.format("%02d:%02d:%02d.%02d", hours, minutes, seconds, millis); } else { res = String.format("%dd%02d:%02d:%02d.%02d", days, hours, minutes, seconds, millis); }
Rick Barkhouse 2013年

10

您可以使用Perf4j。非常酷的实用程序。用法很简单

String watchTag = "target.SomeMethod";
StopWatch stopWatch = new LoggingStopWatch(watchTag);
Result result = null; // Result is a type of a return value of a method
try {
    result = target.SomeMethod();
    stopWatch.stop(watchTag + ".success");
} catch (Exception e) {
    stopWatch.stop(watchTag + ".fail", "Exception was " + e);
    throw e; 
}

可在《开发人员指南》中找到更多信息

编辑:项目似乎死了


1
Perf4j也可以生成不错的统计信息
Paaske 2012年

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 2013年

7

我基本上会做一些变体,但是考虑到热点编译的工作原理,如果要获得准确的结果,则需要排除前几个测量值,并确保在实际(特定于应用程序的读取)应用程序中使用该方法。

如果JIT决定对其进行编译,那么您的数量将相差很大。所以要注意


7

使用AOP / AspectJ和@Loggable来自jcabi-aspects的注释,您可以轻松而紧凑地完成它:

@Loggable(Loggable.DEBUG)
public String getSomeResult() {
  // return some value
}

对该方法的每次调用都将被发送到具有DEBUG日志记录级别的SLF4J日志记录设备。并且每个日志消息都将包含执行时间。


7

根据JavaDoc,Spring提供了一个实用程序类org.springframework.util.StopWatch

简单的秒表,允许为多个任务计时,公开总运行时间和每个命名任务的运行时间。

用法:

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;
}

可以与AspectJ一起使用吗?
zygimantus

7

我已经编写了一种方法,以一种易于阅读的形式打印该方法的执行时间。例如,要计算100万的阶乘,大约需要9分钟。因此执行时间被打印为:

Execution Time: 9 Minutes, 36 Seconds, 237 MicroSeconds, 806193 NanoSeconds

代码在这里:

public class series
{
    public static void main(String[] args)
    {
        long startTime = System.nanoTime();

        long n = 10_00_000;
        printFactorial(n);

        long endTime = System.nanoTime();
        printExecutionTime(startTime, endTime);

    }

    public static void printExecutionTime(long startTime, long endTime)
    {
        long time_ns = endTime - startTime;
        long time_ms = TimeUnit.NANOSECONDS.toMillis(time_ns);
        long time_sec = TimeUnit.NANOSECONDS.toSeconds(time_ns);
        long time_min = TimeUnit.NANOSECONDS.toMinutes(time_ns);
        long time_hour = TimeUnit.NANOSECONDS.toHours(time_ns);

        System.out.print("\nExecution Time: ");
        if(time_hour > 0)
            System.out.print(time_hour + " Hours, ");
        if(time_min > 0)
            System.out.print(time_min % 60 + " Minutes, ");
        if(time_sec > 0)
            System.out.print(time_sec % 60 + " Seconds, ");
        if(time_ms > 0)
            System.out.print(time_ms % 1E+3 + " MicroSeconds, ");
        if(time_ns > 0)
            System.out.print(time_ns % 1E+6 + " NanoSeconds");
    }
}

6

有两种方法可以做到这一点。我通常会退回到只使用这样的东西:

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

或与System.nanoTime()相同;

对于基准测试方面的更多内容,似乎也有这样的内容:http : //jetm.void.fm/尽管从未尝试过。


6

您可以使用提供各种测量仪器的Metrics库。添加依赖项:

<dependencies>
    <dependency>
        <groupId>io.dropwizard.metrics</groupId>
        <artifactId>metrics-core</artifactId>
        <version>${metrics.version}</version>
    </dependency>
</dependencies>

并根据您的环境进行配置。

可以使用@Timed注释方法:

@Timed
public void exampleMethod(){
    // some code
}

或用Timer包装的一段代码:

final Timer timer = metricsRegistry.timer("some_name");
final Timer.Context context = timer.time();
// timed code
context.stop();

汇总指标可以导出到控制台,JMX,CSV或其他。

@Timed 指标输出示例:

com.example.ExampleService.exampleMethod
             count = 2
         mean rate = 3.11 calls/minute
     1-minute rate = 0.96 calls/minute
     5-minute rate = 0.20 calls/minute
    15-minute rate = 0.07 calls/minute
               min = 17.01 milliseconds
               max = 1006.68 milliseconds
              mean = 511.84 milliseconds
            stddev = 699.80 milliseconds
            median = 511.84 milliseconds
              75% <= 1006.68 milliseconds
              95% <= 1006.68 milliseconds
              98% <= 1006.68 milliseconds
              99% <= 1006.68 milliseconds
            99.9% <= 1006.68 milliseconds

5

如果您想要挂钟时间

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

5

正如“ skaffman”所说,使用AOP OR可以使用运行时字节码编织,就像单元测试方法覆盖工具用来透明地将计时信息添加到调用的方法一样。

您可以查看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

如果您最终设法按照自己的意愿去做,请。与您的蚂蚁任务/罐子在这里与社区共享。



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);

4

您可以使用spring核心项目中的秒表类:

码:

StopWatch stopWatch = new StopWatch()
stopWatch.start();  //start stopwatch
// write your function or line of code.
stopWatch.stop();  //stop stopwatch
stopWatch.getTotalTimeMillis() ; ///get total time

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


3

如果只想知道时间,可以尝试这种方式。

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

3

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

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

3

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

即时表示时间线上十亿分之一秒的开始。此类对于生成表示机器时间的时间戳很有用。瞬时范围需要存储大于整数的数字。为实现此目的,该类存储一个长整数(代表纪元秒)和一个整数(代表毫微秒数),该整数始终在0到999,999,999之间。纪元秒是从1970-01-01T00:00:00Z的标准Java纪元开始测量的,其中纪元后的时刻具有正值,而较早的时刻具有负值。对于时代秒和纳秒部分,始终在时间线上晚于较大值,而不是较小值。

可以用作:

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.