Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么执行Mockito mock的性能如此不稳定?_Java_Performance_Mockito - Fatal编程技术网

Java 为什么执行Mockito mock的性能如此不稳定?

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 (

对于执行Mockito mocks所花费的时间如此不稳定的原因,有人能给出解释,或者更好的建议解决方案吗?我能想到的最简单的SSCCE如下:

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的大多数人都要丰富

以下是该测试存在缺陷的最显著方式

  • 测试忽略了JVM正在做的事情,比如预热阶段、编译C1和C2线程、GC、线程问题(即使此代码不是多线程的,JVM/OS可能还需要做其他事情)等等

  • 如果实际的OS/JVM/CPU组合提供高达纳秒的正确分辨率,那么测试似乎忽略了这一点

    即使存在
    System.nanoTime()
    ,您是否确定JVM和操作系统具有正确的分辨率。例如,在windows上,JVM无法访问真正的纳秒,而是访问某个计数器,而不是挂钟时间。状态如下,下面是代码片段:

    此方法只能用于测量经过的时间,与系统或挂钟时间的任何其他概念无关。返回的值表示自某个固定但任意的起始时间起的纳秒(可能在将来,因此值可能为负数)。Java虚拟机实例中此方法的所有调用都使用相同的源;其他虚拟机实例可能使用不同的源

    此方法提供纳秒精度,但不一定是纳秒分辨率(即值更改的频率)
    除了分辨率至少与currentTimeMillis()的分辨率一样好之外,不作任何保证

  • 该测试还忽略了Mockito的工作原理

    Mockito将每个调用存储在自己的模型中,以便在执行场景后能够验证这些调用。因此,在循环的每次迭代中,Mockito将存储另一个调用,最多2百万次调用,这将影响JVM(可能mock实例将保留几代,并提升为终身,这对GC来说肯定会更昂贵)。这意味着迭代次数越多,代码对JVM的压力就越大,而不是Mockito

    我相信它还没有发布(不过jcentral上有dev二进制文件),但是Mockito将提供一个设置,只允许Mockito存根,因此它不会存储调用,这可能使Mockito能够很好地适应这样的场景

  • 这项测试缺乏适当的统计分析

    有趣的是,测试代码有一个伪百分位数的方法。这很好!虽然它不是这样工作的,在这种情况下,它不能抓住大问题。相反,它应该记录每个度量,以便提取mockito随着迭代计数的推进所花费时间的演变趋势

    如果您愿意,最好存储每个记录的度量值,这样就可以将它们提供给适当的统计分析工具,如R,以便提取图表、百分位数据等

    在这个统计问题上,在微基准之外使用.当然是很有趣的,因为它会影响内存并改变微基准的结果。让我们为JMH保留这一点

  • 如果您将代码更改为使用JMH,那么第1点和第2点都可以解决1999983, 4, 9, 4 Longest duration was 5227445252 ns