我有一个自己用Java编写的程序,但是我想测试方法执行时间并获得特定方法的时间。我想知道是否可能通过Eclipse插件或插入一些代码来实现这一点。
我看到这是相当小的程序,只有不到1500行代码,最好使用专门的工具还是 System.currentTimeMillis()
?
我有一个自己用Java编写的程序,但是我想测试方法执行时间并获得特定方法的时间。我想知道是否可能通过Eclipse插件或插入一些代码来实现这一点。
我看到这是相当小的程序,只有不到1500行代码,最好使用专门的工具还是 System.currentTimeMillis()
?
除了使用分析器之外,获取你想要的东西的一个简单方法是:
public class SomeClass{
public void somePublicMethod()
{
long startTime = System.currentTimeMillis();
someMethodWhichYouWantToProfile();
long endTime = System.currentTimeMillis();
System.out.println("Total execution time: " + (endTime-startTime) + "ms");
}
}
-XX:CompileThreshold=100
标志,当方法被执行100次时,你可以强制JVM将其编译为本地代码。因此,在不计时的情况下,你可以执行它100次。之后,它已经被编译成本地代码,你可以正确地测量它。 - Christophe De Troyer如果瓶颈足够大,可以用分析器检测,使用分析器。
如果您需要更高的准确性,测量小段代码最好的方法是使用Java微基准测试框架,如OpenJDK的JMH或Google的Caliper。我相信它们像JUnit一样容易使用,不仅可以获得更准确的结果,还能从社区中获得正确操作的专业知识。
以下是一个JMH微基准测试,用于测量Math.log()
的执行时间:
private double x = Math.PI;
@Benchmark
public void myBenchmark() {
return Math.log(x)
}
使用currentMillis()
和nanoTime()
进行测量有许多限制:
Java中的currentMillis()
和nanoTime()
方法可能很有用,但必须极其小心地使用,否则就会出现错误的测量结果,例如这样,其中测量的代码片段的顺序会影响测量结果,或者这样,作者错误地得出结论,即执行了数百万次操作,而实际上JVM没有执行任何操作并提升了代码,根本没有运行任何代码。
这是一段精彩的视频,讲解了如何正确地进行微基准测试:https://shipilev.net/#benchmarking
如果需要进行快速而简单的时间测量测试,请不要使用挂钟时间(System.currentTimeMillis()
)。建议改用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.
}
Google Guava有一个秒表,让事情变得简单易行。
Stopwatch stopwatch = Stopwatch.createStarted();
myFunctionCall();
LOGGER.debug("Time taken by myFunctionCall: " + stopwatch.stop());
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();
另一种定制解决方案可以基于以下帖子:http://www.mkyong.com/spring/spring-aop-examples-advice/
您还可以使用应用程序监视和SNMP周围的实用工具。如果您需要在生产环境中定期“计时”方法,则可能应考虑使用其中一个SNMP工具。
long millisecondsStart = System.currentTimeMillis();
executeMethod();
long timeSpentInMilliseconds = System.currentTimeMillis() - millisecondsStart;
executeMethod()
方法的时间加上System.currentTimeMillis()
的时间。3)这并没有考虑JVM预热效应,例如JIT编译。 - Stephen C
System.nanoTime()
而不是System.currentTimeMillis()
(请参考https://dev59.com/J3VC5IYBdhLWcg3wnCf6#239661)。其他点(预热、JIT)由评论中提到的@Stephen仍然有效。 - Pascal Thivent