Java 性能测试
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/447739/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java Performance Testing
提问by mainstringargs
I want to do some timing tests on a Java application. This is what I am currently doing:
我想对 Java 应用程序进行一些计时测试。这就是我目前正在做的事情:
long startTime = System.currentTimeMillis();
doSomething();
long finishTime = System.currentTimeMillis();
System.out.println("That took: " + (finishTime - startTime) + " ms");
Is there anything "wrong" with performance testing like this? What is a better way?
像这样的性能测试有什么“错误”吗?什么是更好的方法?
Duplicate: Is stopwatch benchmarking acceptable?
采纳答案by MattK
The one flaw in that approach is that the "real" time doSomething()
takes to execute can vary wildly depending on what other programs are running on the system and what its load is. This makes the performance measurement somewhat imprecise.
这种方法的一个缺陷是,doSomething()
根据系统上正在运行的其他程序及其负载,“实际”执行时间可能会有很大差异。这使得性能测量有些不精确。
One more accurate way of tracking the time it takes to execute code, assuming the code is single-threaded, is to look at the CPU time consumed by the thread during the call. You can do this with the JMX classes; in particular, with ThreadMXBean
. You can retrieve an instance of ThreadMXBean
from java.lang.management.ManagementFactory
, and, if your platform supports it (most do), use the getCurrentThreadCpuTime
method in place of System.currentTimeMillis
to do a similar test. Bear in mind that getCurrentThreadCpuTime
reports time in nanoseconds, not milliseconds.
假设代码是单线程的,跟踪执行代码所需时间的一种更准确的方法是查看线程在调用期间消耗的 CPU 时间。您可以使用 JMX 类来做到这一点;特别是,与ThreadMXBean
。您可以检索ThreadMXBean
from的实例java.lang.management.ManagementFactory
,并且,如果您的平台支持它(大多数都支持),请使用该getCurrentThreadCpuTime
方法代替 ofSystem.currentTimeMillis
进行类似的测试。请记住,getCurrentThreadCpuTime
以纳秒为单位报告时间,而不是毫秒。
Here's a sample (Scala) method that could be used to perform a measurement:
这是可用于执行测量的示例 (Scala) 方法:
def measureCpuTime(f: => Unit): java.time.Duration = {
import java.lang.management.ManagementFactory.getThreadMXBean
if (!getThreadMXBean.isThreadCpuTimeSupported)
throw new UnsupportedOperationException(
"JVM does not support measuring thread CPU-time")
var finalCpuTime: Option[Long] = None
val thread = new Thread {
override def run(): Unit = {
f
finalCpuTime = Some(getThreadMXBean.getThreadCpuTime(
Thread.currentThread.getId))
}
}
thread.start()
while (finalCpuTime.isEmpty && thread.isAlive) {
Thread.sleep(100)
}
java.time.Duration.ofNanos(finalCpuTime.getOrElse {
throw new Exception("Operation never returned, and the thread is dead " +
"(perhaps an unhandled exception occurred)")
})
}
(Feel free to translate the above to Java!)
(请随意将以上内容翻译成 Java!)
This strategy isn't perfect, but it's less subject to variations in system load.
这种策略并不完美,但它受系统负载变化的影响较小。
回答by Kent Boogaart
I'd imagine you'd want to doSomething() before you start timing too, so that the code is JITted and "warmed up".
我想你也想在开始计时之前做一些事情(),以便代码被 JITted 和“热身”。
回答by Josh Harris
Well that is just one part of performance testing. Depending on the thing you are testing you may have to look at heap size, thread count, network traffic or a whole host of other things. Otherwise I use that technique for simple things that I just want to see how long they take to run.
嗯,这只是性能测试的一部分。根据您正在测试的内容,您可能需要查看堆大小、线程数、网络流量或其他大量内容。否则,我会将这种技术用于简单的事情,我只是想看看它们运行需要多长时间。
回答by Steve Kuo
Keep in mind that the resolution of System.currentTimeMillis()
varies between different operating systems. I believe Windows is around 15 msec. So if your doSomething()
runs faster than the time resolution, you'll get a delta of 0. You could run doSomething()
in a loop multiple times, but then the JVM may optimize it.
请记住,System.currentTimeMillis()
不同操作系统之间的分辨率不同。我相信 Windows 大约是 15 毫秒。因此,如果您的doSomething()
运行速度比时间分辨率快,您将获得 0 的增量。您可以doSomething()
在循环中多次运行,但 JVM 可能会对其进行优化。
回答by Bill K
That's good when you are comparing one implementation to another or trying to find a slow part in your code (although it can be tedious). It's a really good technique to know and you'll probably use it more than any other, but be familiar with a profiling tool as well.
当您将一种实现与另一种实现进行比较或试图在代码中找到缓慢的部分时,这很好(尽管它可能很乏味)。这是一项非常好的技术,您可能会比其他任何技术都更频繁地使用它,但也要熟悉分析工具。
回答by Milhous
回答by Rich Apodaca
回答by Ran Biron
The code shown in the question is not a good performance measuring code:
问题中显示的代码不是一个好的性能测量代码:
The compiler might choose to optimize your code by reordering statements. Yes, it can do that. That means your entire test might fail. It can even choose to inline the method under test and reorder the measuring statements into the now-inlined code.
The hotspot might choose to reorder your statements, inline code, cache results, delay execution...
Even assuming the compiler/hotspot didn't trick you, what you measure is "wall time". What you should be measuring is CPU time (unless you use OS resources and want to include these as well or you measure lock contestation in a multi-threaded environment).
编译器可能会选择通过重新排序语句来优化您的代码。是的,它可以做到这一点。这意味着您的整个测试可能会失败。它甚至可以选择内联被测方法并将测量语句重新排序为现在内联的代码。
热点可能会选择重新排序您的语句、内联代码、缓存结果、延迟执行...
即使假设编译器/热点没有欺骗您,您测量的也是“挂墙时间”。您应该测量的是 CPU 时间(除非您使用操作系统资源并希望包含这些资源,或者您在多线程环境中测量锁争用)。
The solution? Use a real profiler. There are plenty around, both free profilers and demos / time-locked trials of commercials strength ones.
解决方案?使用真正的分析器。周围有很多免费的分析器和演示/时间锁定的商业广告试用版。
回答by M.N
Using a Java Profiler is the best option and it will give you all the insight that you need into the code. viz Response Times, Thread CallTraces, Memory Utilisations, etc
使用 Java Profiler 是最好的选择,它将为您提供对代码所需的所有洞察。即响应时间、线程调用跟踪、内存利用率等
I will suggest you JENSOR, an open source Java Profiler, for its ease-of-use and no overheads on CPU. You can download it, instrument the code and will get all the info you need about your code.
我会向您推荐 JENSOR,这是一个开源 Java Profiler,因为它易于使用且没有 CPU 开销。您可以下载它,检测代码并获得您需要的关于代码的所有信息。
You can download it from: http://jensor.sourceforge.net/
:你可以从这里下载http://jensor.sourceforge.net/