Java 为什么执行Mockito mock的性能如此不稳定?
对于执行Mockito mocks所花费的时间如此不稳定的原因,有人能给出解释,或者更好的建议解决方案吗?我能想到的最简单的SSCCE如下:Java 为什么执行Mockito mock的性能如此不稳定?,java,performance,mockito,Java,Performance,Mockito,对于执行Mockito mocks所花费的时间如此不稳定的原因,有人能给出解释,或者更好的建议解决方案吗?我能想到的最简单的SSCCE如下: import static org.mockito.Mockito.mock; public class TestSimpleMockTiming { public static final void main (final String args []) { final Runnable theMock = mock (
import static org.mockito.Mockito.mock;
public class TestSimpleMockTiming
{
public static final void main (final String args [])
{
final Runnable theMock = mock (Runnable.class);
int tookShort = 0;
int tookMedium = 0;
int tookLong = 0;
int tookRidiculouslyLong = 0;
long longest = 0;
for (int n = 0; n < 2000000; n++)
{
final long startTime = System.nanoTime ();
theMock.run ();
final long duration = System.nanoTime () - startTime;
if (duration < 1000000) // 0.001 seconds
tookShort++;
else if (duration < 100000000) // 0.1 seconds
tookMedium++;
else if (duration < 1000000000) // 1 second !!!
tookLong++;
else
tookRidiculouslyLong++;
longest = Math.max (longest, duration);
}
System.out.println (tookShort + ", " + tookMedium + ", " + tookLong + ", " + tookRidiculouslyLong);
System.out.println ("Longest duration was " + longest + " ns");
}
}
因此,虽然在大多数情况下模拟执行速度非常快,但有几个执行时间甚至超过1秒。对于一个什么都不做的方法来说,这是永恒的。从我的实验来看,我不认为问题在于System.nanoTime()的准确性,我认为模拟真的需要那么长时间才能执行。我能做些什么来改进这一点,使时间安排更加一致吗
(仅供参考,这是一个问题的原因是我有一个包含各种帧的Swing应用程序,我尝试为这些帧编写JUnit测试,这样我就可以测试LayoutManager的行为是否正确,而无需启动整个应用程序并导航到正确的屏幕。在一个这样的测试中,屏幕使用javax.Swing.Timer来实现滚动,因此当鼠标靠近画面末端时,显示屏将在一个区域内平移。我注意到这种情况非常不稳定,在正常情况下,滚动会周期性地冻结一秒钟,看起来很糟糕。我写了一篇SSCCE文章,认为问题在于不能依靠摆动计时器来触发一个一致的速率,在SSCCE中它工作得非常好
在数小时的紧张工作后,我开始在反复运行的代码块周围放置nano计时器,注意到我的paintComponent方法花费的时间非常不稳定,并最终将其缩小为模拟调用。通过运行在真正的应用程序中,滚动运行平稳,这只是JUnit测试中的一个问题,因为mock调用,这导致我在与上面发布的SSCCE隔离的情况下测试了一个简单的mock。)
非常感谢!JVM是一件非常复杂的事情,它在运行时进行了大量优化(包括缓存和字节码优化)。因此,衡量Java程序的执行时间,首先应该在进行实际基准测试之前进行预热阶段 我预计你的前四次跑步花费了你最长的盈利时间,之后,执行时间变得越来越好
在您真正开始评测之前,执行您的基准测试几百次或数千次。之后,我希望您的测量结果会变得更稳定。此测试在多个方面存在缺陷。如果您想正确地进行基准测试,我强烈建议使用,它是由某个人完成的Alexey Shipilev,这是非常困难的比我们聪明,而且在JVM方面的知识绝对比在我们热爱的星球上使用Java的大多数人都要丰富 以下是该测试存在缺陷的最显著方式
System.nanoTime()
,您是否确定JVM和操作系统具有正确的分辨率。例如,在windows上,JVM无法访问真正的纳秒,而是访问某个计数器,而不是挂钟时间。状态如下,下面是代码片段:
此方法只能用于测量经过的时间,与系统或挂钟时间的任何其他概念无关。返回的值表示自某个固定但任意的起始时间起的纳秒(可能在将来,因此值可能为负数)。Java虚拟机实例中此方法的所有调用都使用相同的源;其他虚拟机实例可能使用不同的源
此方法提供纳秒精度,但不一定是纳秒分辨率(即值更改的频率)除了分辨率至少与currentTimeMillis()的分辨率一样好之外,不作任何保证
1999983, 4, 9, 4
Longest duration was 5227445252 ns