How can i benchmark method execution time in java?

JavaOptimization

Java Problem Overview


I have a program which i have myself written in java, but I want to test method execution times and get timings for specific methods. I was wondering if this is possible, by maybe somehow an eclipse plug-in? or maybe inserting some code?

I see, it is quite a small program, nothing more than 1500 lines, which would be better a dedicated tool or System.currentTimeMillis()?

Java Solutions


Solution 1 - Java

Other than using a profiler, a simple way of getting what you want is the following:

public class SomeClass{
   public void somePublicMethod()
   {
       long startTime = System.currentTimeMillis();
       someMethodWhichYouWantToProfile();
       long endTime = System.currentTimeMillis();
       System.out.println("Total execution time: " + (endTime-startTime) + "ms"); 
   }
 }

Solution 2 - Java

If the bottleneck is big enough to be observed with a profiler, use a profiler.

If you need more accuracy, the best way of measuring an small piece of code is the use of a Java microbenchmark framework like [OpenJDK's JMH][3] or [Google's Caliper][4]. I believe they are as simple to use as JUnit and not only you will get more accurate results, but you will gain the expertise from the community to do it right.

Follows a JMH microbenchmark to measure the execution time of Math.log():

private double x = Math.PI;

@Benchmark
public void myBenchmark() {
    return Math.log(x)
}

Using the currentMillis() and nanoTime() for measuring has many limitations:

  1. They have latency (they also take time to execute) which bias your measurements.
  2. They have VERY limited precision, this means you can mesure things from 26ns to 26ns in linux and 300 or so in Windows has described [here][5]
  3. The warmup phase is not taken into consideration, making your measurements fluctuate A LOT.

The currentMillis() and nanoTime() methods in Java can be useful but must be used with EXTREME CAUTION or you can get wrong measurements errors [like this][1] where the order of the measured snippets influence the measurements or [like this][2] where the author wrongly conclude that several millions of operations where performed in less than a ms, when in fact the JMV realised no operations where made and hoisted the code, running no code at all.

Here is a wonderful video explaining how to microbenchmark the right way: https://shipilev.net/#benchmarking

[1]: http://howtodoinjava.com/core-java/related-concepts/performance-comparison-of-different-for-loops-in-java/ "like this" [2]: https://www.javacodegeeks.com/2011/09/java-micro-benchmarking-how-to-write.html "like this" [3]: http://openjdk.java.net/projects/code-tools/jmh/ [4]: https://github.com/google/caliper [5]: http://shipilev.net/blog/2014/nanotrusting-nanotime/#_one_off_measurements

Solution 3 - Java

For quick and dirty time measurement tests, don't use wall-clock time (System.currentTimeMillis()). Prefer System.nanoTime() instead:

public static void main(String... ignored) throws InterruptedException {
    final long then = System.nanoTime();
    TimeUnit.SECONDS.sleep(1);
    final long millis = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - then);
    System.out.println("Slept for (ms): " + millis); // = something around 1000.
}

Solution 4 - Java

You should use a profiler like

They will easily integrate with any IDE and show whatever detail you need.

Of course these tools are complex and meant to be used to profile complex programs, if you need just some simple benchmarks I suggest you to use System.currentTimeMillis() or System.nanoTime() and calculate delta of millisecs between calls by yourself.

Solution 5 - Java

Using a profiler is better because you can find out average execution times and bottlenecks in your app.

I use VisualVM. slick and simple.

Solution 6 - Java

Google Guava has a stopwatch, makes things simple and easy.

Stopwatch stopwatch = Stopwatch.createStarted();
myFunctionCall();
LOGGER.debug("Time taken by myFunctionCall: " + stopwatch.stop());

Solution 7 - Java

Jprofiler and yourkit are good, but cost money.

There is a free plugin for eclispe called TPTP (Test & Performance Tools Platform) That can give you code execution times. Here is a tutorial that a quick google search brought up. http://www.eclipse.org/articles/Article-TPTP-Profiling-Tool/tptpProfilingArticle.html

Solution 8 - Java

Another Custom made solution could be based on the the following post : http://www.mkyong.com/spring/spring-aop-examples-advice/

You then have also the possibility to use the utilities around application monitoring & snmp. If you need to "time" your methods on a regular basis in a production environment, you proabably should consider using one of the those SNMP tools

Solution 9 - Java

You can add this code and it will tell you how long the method took to execute.

long millisecondsStart = System.currentTimeMillis();
executeMethod();
long timeSpentInMilliseconds = System.currentTimeMillis() - millisecondsStart;

Solution 10 - Java

Usually I store the time in a .txt file for analise the outcome

StopWatch sWatch = new StopWatch();
sWatch.start();

//do stuff that you want to measure
downloadContent();

sWatch.stop();

//make the time pretty
long timeInMilliseconds = sWatch.getTime();
long hours = TimeUnit.MILLISECONDS.toHours(timeInMilliseconds);
long minutes = TimeUnit.MILLISECONDS.toMinutes(timeInMilliseconds - TimeUnit.HOURS.toMillis(hours));
long seconds = TimeUnit.MILLISECONDS.toSeconds(timeInMilliseconds - TimeUnit.HOURS.toMillis(hours) - TimeUnit.MINUTES.toMillis(minutes));
long milliseconds = timeInMilliseconds - TimeUnit.HOURS.toMillis(hours) - TimeUnit.MINUTES.toMillis(minutes) - TimeUnit.SECONDS.toMillis(seconds);

String t = String.format("%02d:%02d:%02d:%d", hours, minutes, seconds, milliseconds);

//each line to store in a txt file, new line
String content = "Ref: " + ref + "  -  " + t + "\r\n";

//you may want wrap this section with a try catch
File file = new File("C:\\time_log.txt");
FileWriter fw = new FileWriter(file.getAbsoluteFile(), true); //append content set to true, so it does not overwrite existing data
BufferedWriter bw = new BufferedWriter(fw);
bw.write(content);
bw.close();

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKP65View Question on Stackoverflow
Solution 1 - JavaChris KnightView Answer on Stackoverflow
Solution 2 - JavaEl MarceView Answer on Stackoverflow
Solution 3 - JavaMartin AnderssonView Answer on Stackoverflow
Solution 4 - JavaJackView Answer on Stackoverflow
Solution 5 - JavaMidhatView Answer on Stackoverflow
Solution 6 - JavazengrView Answer on Stackoverflow
Solution 7 - JavathattmattView Answer on Stackoverflow
Solution 8 - Javauser2991363View Answer on Stackoverflow
Solution 9 - JavaShervin AsgariView Answer on Stackoverflow
Solution 10 - JavaPhilippeView Answer on Stackoverflow