如何在Java中确定某行代码的执行时间?

3
假设我有一些代码,我想将其最大程度地优化,而不考虑可读性、可维护性等等。
为此,有没有办法找出每个基本动作需要多长时间?我认为这可能取决于CPU,但我不确定。
我的意思是像循环for、赋值a=24、数学运算2+25等等。

那么我怎么知道 System.nanoTime() 需要多少时间呢?这肯定会增加相当多的时间。 - YoTengoUnLCD
他的意思是在两条指令之间使用当前纳秒时间可以获得执行时间。 - Benoit Vanalderweireldt
@BenoitVanalderweireldt 好吧,假设我执行 System.nanoTime(); 2+25; System.nanoTime(); 如果nanoTime花费0秒完成,则可以知道执行2+25所需的时间,但这还包括执行System.nanoTime()所需的时间。 - YoTengoUnLCD
3
你不能这样做。那个“代码行”已经被翻译成了字节码,在程序的单次启动过程中可能会以几种不同的方式执行。 - chrylis -cautiouslyoptimistic-
基准测试很难。而你所寻找的粒度更加困难。除了使用像JMH这样的好框架来测量Java代码之外,你还可以使用Java或操作系统分析器。有些甚至集成到JMH中。http://www.oracle.com/technetwork/articles/java/architect-benchmarking-2266277.html - eckes
显示剩余4条评论
2个回答

7

上下文很重要。各种Java语言结构的固定成本并不存在,您不能只是将它们相加以获得有用的运行时估计。您似乎希望得到的答案不存在。

即使您成功设计了一个正确的微基准测试来衡量某些if()switch之间的差异,结果也会严重依赖于周围代码、案例的细节和分支的可预测性。制作微基准测试很难。除非您查看实际在循环中运行的机器指令,否则您经常会测量到其他东西。如果您不使用结果,好的编译器也可以轻松地优化掉您的循环,但是如果您使用结果,则很难以一种不会产生比您要测量的更多开销的方式使用结果。

一个好的JIT-编译器JVM应该生成的机器代码不会比您所希望的差太多,因此,如果您对C如何编译为ASM有很好的了解,那么这可能对Java有用。

如果您想了解现代x86微架构上快速与慢速的内容,请查看Agner Fog的指南

一个好的分析工具可以帮助您确定您的代码是CPU绑定还是受到内存(缓存未命中:内存带宽或延迟)或分支错误预测的限制。我没有为Java做过这件事,但标准工具(如Linux的perf)可能有效,只要您使用足够长的运行时间来隐藏JVM启动的开销。


0
你可以这样做:
long startTime = System.currentTimeMillis();
// ---- Your code ----
long endTime = System.currentTimeMillis()
System.out.println("The previous line took " + (endTime - startTime) + " ms");

这两个调用:System.out.println; System.currentTimeInMillis 不会在前一行完成和输出之间增加太多时间吗? - YoTengoUnLCD
如果你想更准确,可以使用更细粒度的时间测量,比如nanoTime - David Fernandez

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接