How do I time a method's execution in Java?

2018-12-31 02:15发布

How do I get a method's execution time? Is there a Timer utility class for things like timing how long a task takes, etc?

Most of the searches on Google return results for timers that schedule threads and tasks, which is not what I want.

标签: java timing
30条回答
情到深处是孤独
2楼-- · 2018-12-31 02:19

Come on guys! Nobody mentioned the Guava way to do that (which is arguably awesome):

import com.google.common.base.Stopwatch;

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

The nice thing is that Stopwatch.toString() does a good job of selecting time units for the measurement. I.e. if the value is small, it'll output 38 ns, if it's long, it'll show 5m 3s

Even nicer:

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

Note: Google Guava requires Java 1.6+

查看更多
梦醉为红颜
3楼-- · 2018-12-31 02:19

Really good code.

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;
  }
查看更多
浮光初槿花落
4楼-- · 2018-12-31 02:20

I basically do variations of this, but considering how hotspot compilation works, if you want to get accurate results you need to throw out the first few measurements and make sure you are using the method in a real world (read application specific) application.

If the JIT decides to compile it your numbers will vary heavily. so just be aware

查看更多
倾城一夜雪
5楼-- · 2018-12-31 02:20

You can use Metrics library which provides various measuring instruments. Add dependency:

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

And configure it for your environment.

Methods can be annotated with @Timed:

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

or piece of code wrapped with Timer:

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

Aggregated metrics can exported to console, JMX, CSV or other.

@Timed metrics output example:

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
查看更多
低头抚发
6楼-- · 2018-12-31 02:21

I go with the simple answer. Works for me.

long startTime = System.currentTimeMillis();

doReallyLongThing();

long endTime = System.currentTimeMillis();

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

It works quite well. The resolution is obviously only to the millisecond, you can do better with System.nanoTime(). There are some limitations to both (operating system schedule slices, etc.) but this works pretty well.

Average across a couple of runs (the more the better) and you'll get a decent idea.

查看更多
梦该遗忘
7楼-- · 2018-12-31 02:21

JEP 230: Microbenchmark Suite

FYI, JEP 230: Microbenchmark Suite is an OpenJDK proposal to:

Add a basic suite of microbenchmarks to the JDK source code, and make it easy for developers to run existing microbenchmarks and create new ones.

This proposal did not make the cut for Java 9 but may be added later.

Java Microbenchmark Harness (JMH)

In the meantime you may want to look at the Java Microbenchmark Harness (JMH) project on which the proposal is based.

查看更多
登录 后发表回答