简体   繁体   English

我如何在 Java 中对方法执行时间进行基准测试?

[英]How can i benchmark method execution time in java?

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.我有一个我自己用 java 编写的程序,但我想测试方法执行时间并获取特定方法的时间。 I was wondering if this is possible, by maybe somehow an eclipse plug-in?我想知道这是否可能,也许是一个 eclipse 插件? 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() ?我明白了,它是一个很小的程序,不超过 1500 行,哪个更好用专用工具或System.currentTimeMillis()

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

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 or Google's Caliper .如果您需要更高的准确性,衡量一小段代码的最佳方法是使用 Java 微基准测试框架,例如OpenJDK 的 JMHGoogle 的 Caliper 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.我相信它们与 JUnit 一样易于使用,不仅您将获得更准确的结果,而且您​​将从社区获得专业知识以正确执行此操作。

Follows a JMH microbenchmark to measure the execution time of Math.log() :遵循 JMH 微基准测试来测量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:使用currentMillis()nanoTime()进行测量有很多限制:

  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它们的精度非常有限,这意味着您可以测量 linux 中 26ns 到 26ns 和 Windows 中 300 左右的内容,已在此处描述
  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 where the order of the measured snippets influence the measurements or like this 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.currentMillis()nanoTime()在Java方法可能是有用的,但必须慎用或你可以得到错误的测量结果的误差像这样被测量的片段的顺序影响测量或像这样在这里笔者错误地得出结论,几个在不到一毫秒的时间内执行了数百万次操作,而实际上 JMV 没有实现任何操作并提升代码,根本不运行任何代码。

Here is a wonderful video explaining how to microbenchmark the right way: https://shipilev.net/#benchmarking这是一个精彩的视频,解释了如何以正确的方式进行微基准测试: https : //shipilev.net/#benchmarking

For quick and dirty time measurement tests, don't use wall-clock time ( System.currentTimeMillis() ).对于快速和肮脏的时间测量测试,不要使用挂钟时间( System.currentTimeMillis() )。 Prefer System.nanoTime() instead:更喜欢System.nanoTime()

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

You should use a profiler like您应该使用类似的分析器

They will easily integrate with any IDE and show whatever detail you need.它们将轻松与任何 IDE 集成并显示您需要的任何细节。

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.当然,这些工具很复杂,旨在用于分析复杂的程序,如果您只需要一些简单的基准测试,我建议您使用System.currentTimeMillis()System.nanoTime()System.nanoTime()计算调用之间的毫秒增量。

Using a profiler is better because you can find out average execution times and bottlenecks in your app.使用分析器更好,因为您可以找出应用程序中的平均执行时间和瓶颈。

I use VisualVM .我使用VisualVM slick and simple.圆滑而简单。

Google Guava has a stopwatch , makes things simple and easy. Google Guava 有一个秒表,让事情变得简单易行。

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

Jprofiler and yourkit are good, but cost money. Jprofiler 和 yourkit 都不错,但要花钱。

There is a free plugin for eclispe called TPTP (Test & Performance Tools Platform) That can give you code execution times. eclispe 有一个免费插件,称为 TPTP(测试和性能工具平台),它可以为您提供代码执行时间。 Here is a tutorial that a quick google search brought up.这是一个快速谷歌搜索带来的教程。 http://www.eclipse.org/articles/Article-TPTP-Profiling-Tool/tptpProfilingArticle.html http://www.eclipse.org/articles/Article-TPTP-Profiling-Tool/tptpProfilingArticle.html

Another Custom made solution could be based on the the following post : http://www.mkyong.com/spring/spring-aop-examples-advice/另一个定制的解决方案可以基于以下帖子: http : //www.mkyong.com/spring/spring-aop-examples-advice/

You then have also the possibility to use the utilities around application monitoring & snmp.然后,您还可以使用有关应用程序监控和 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如果您需要在生产环境中定期“计时”您的方法,您可能应该考虑使用这些 SNMP 工具之一

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;

Usually I store the time in a .txt file for analise the outcome通常我将时间存储在 .txt 文件中以分析结果

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM