Should I expect code not in a method in Mockito Tests to Run Faster because of Java Just In Time Compilation?

huangapple go评论66阅读模式
英文:

Should I expect code not in a method in Mockito Tests to Run Faster because of Java Just In Time Compilation?

问题

我需要帮助进行一个小实验。我有两个测试文件:

testFileA.javatestFileB.java

testFileA.java 的内容如下:

@Test
public void test1() throws Throwable {
    Instant start = Instant.now();
    mvc.perform(MockMvcRequestBuilders
                    .post('someEndpoint/')
                    .andDo(print())
                    .andExpect(status().isCreated()));
    Instant end = Instant.now();
    System.out.println('>>>>>>>>>>End' + Duration.between(start, end));
}

@Test
public void test2() throws Throwable {
    // 与测试1相同的内容
}

@Test
public void test3() throws Throwable {
    // 与测试1相同的内容
}

testFileB.java 的内容如下:

@Test
public void test1() throws Throwable {
    Instant start = Instant.now();
    this.abstractedCode();
    Instant end = Instant.now();
    System.out.println('>>>>>>>>>>End' + Duration.between(start, end));
}

@Test
public void test2() throws Throwable {
    // 与测试1相同的内容
}

@Test
public void test3() throws Throwable {
    // 与测试1相同的内容
}

public void abstractedCode() {
    mvc.perform(MockMvcRequestBuilders
                    .post('someEndpoint/')
                    .andDo(print())
                    .andExpect(status().isCreated()));
}

我对 testFileB.java 的预期是,第一个测试会花费更长的时间,然后每个后续的测试都不会花费那么长时间,因为重复的代码被重构为一个方法调用;Java JIT 编译器使得我们不必重新编译相同的代码。我的预期得到了证实。

我对 testFileA.java 的预期是,每个测试的时间都会与前一个测试一样长,因为常用代码没有重构为一个函数,但事实并非如此。行为相同,第一个测试花费的时间更长,然后接下来的两个测试时间较短。

我猜想在 JVM 内部发生了一些情况,使得我调用的 mvc.perform() 方法不需要一遍又一遍地重新编译,即使它不在我定义的函数中。这是真的吗?

英文:

I need help with a little experiment. I have two test files:

testFileA.java and testFileB.java

testFileA.java looks like

    @Test
    public void test1() throws Throwable {
        Instant start = Instant.now();
        mvc.perform(MockMvcRequestBuilders
                        .post('someEndpoint/')
                        .andDo(print())
                        .andExpect(status().isCreated())
        Instant end = Instant.now();
        System.out.println(">>>>>>>>>>>>>>>>>End" + Duration.between(start, end));
    }

    @Test
    public void test2() throws Throwable {
        //same contents as test 1
    }

    @Test
    public void test3() throws Throwable {
        //same contents as test 1
    }

testFileB.java looks like

    @Test
    public void test1() throws Throwable {
        Instant start = Instant.now();
        this.abstractedCode();
        Instant end = Instant.now();
        System.out.println(">>>>>>>>>>>>>>>>>End" + Duration.between(start, end));
    }

    @Test
    public void test2() throws Throwable {
           //same contents as test 1
    }

    @Test
    public void test3() throws Throwable {
        //same contents as test 1
    }

    public void abstractedCode(){
      mvc.perform(MockMvcRequestBuilders
                        .post('someEndpoint/')
                        .andDo(print())
                        .andExpect(status().isCreated())
    }

My expectation with testFileB.java is that the first test would take a little longer and then each subsequent test wouldn't take as long because the duplicated code is refactored into a method call; the Java JIT compiler makes it so we wouldn't have to recompile the same code again. My expectation was proven correct.

My expectation with testFileA.java is that each test would take as long as the previous one because the common code wasn't refactored into a function, but that ended up not being true. The behavior was the same, the first test took a little longer and then the next two were shorter.

I'm guessing that something is happening within the JVM that makes it so the mvc.perform() method that I'm calling doesn't have to get recompiled over and over again, the JIT compiler is helping my program out despite the fact that it's not in a function I've defined. Is that true?

答案1

得分: 2

一个明显的毫无回应:你正在错误的地方投入时间。

只有在应用程序运行长时间,调用同一个方法数百万次的情况下,“JIT优化”所带来的收益才会有影响。

JIT的重点不是优化仅在JVM生命周期内被调用一次的测试方法。

也就是说:投入时间去学习如何编写可测试的生产代码和整洁的测试代码。这在这里更加重要。

当然:单元测试套件的执行时间仍然重要。但当这成为问题时,很有可能你面临的是编写不良的测试,例如使用默认超时等等...最终导致测试花费很长时间,甚至是几分钟。这是你关心的事情。但对于单元测试环境来说,你绝对不需要关心JIT魔法。

英文:

A distinct non-answer: you are investing your time in the wrong place.

The gains from "JIT optimisations" only matter in a setup where an application runs for lengthy periods of time, invoking the same method millions of times.

The point of a JIT is NOT to optimize test methods that are invoked ONCE during the lifetime of a JVM.

Meaning: invest your time to train how to write testable production code, and clean test code. That is much more important here.

Of course: the execution time of your unit test suite still matters. But when that turns into an issue, then you are most likely facing poorly written tests, that for example use default timeouts and whatnot ... ending up with a test taking many seconds, if not minutes. That is something you care about. You absolutely do not care about JIT magic though for unit test environments.

huangapple
  • 本文由 发表于 2020年8月19日 22:19:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/63489045.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定