简体   繁体   English

JUnit测试:为什么Maven(Surefire)比在Eclipse上运行慢得多?

[英]JUnit Tests: Why is Maven (Surefire) so much slower than running on Eclipse?

I'm working on a fairly big application, with ~260k LOC and roughly 1800 unit tests on the suite. 我正在开发一个相当大的应用程序,在套件上有大约260k LOC和大约1800个单元测试。 A little background: 一点背景:

  1. Multi-modular Maven project 多模块Maven项目
  2. All tests run on a separate module and JaCoCo is used to check coverage. 所有测试都在一个单独的模块上运行,JaCoCo用于检查覆盖范围。
  3. Tests are put together in some suites and then the suites are included on Surefire's configuration. 测试在一些套件中组合在一起,然后套件包含在Surefire的配置中。
  4. Using SpringJUnit4ClassRunner to run the tests 使用SpringJUnit4ClassRunner来运行测试
  5. Surefire is currently configured to use the same VM to build and test ( forkCount equals one and reuseForks equals true). Surefire目前配置为使用相同的VM来构建和测试( forkCount等于1, reuseForks等于true)。 Doing this I am sure I'm using the advantages of Spring's Static Context Cache (reuse the same ApplicationContext on every test) 这样做我确信我正在使用Spring的静态上下文缓存的优点(在每个测试中重用相同的ApplicationContext

When we run tests on our development VMs, using Oracle JDK 7u79/80 we see very fast tests. 当我们在开发虚拟机上运行测试时,使用Oracle JDK 7u79 / 80,我们看到了非常快速的测试。 For example, a fairly big test class with 50+ test methods takes something around 1:30m (including context initialisation time) to run. 例如,具有50多种测试方法的相当大的测试类需要大约1:30m(包括上下文初始化时间)才能运行。

Our basic Dev VM is something like: 我们的基本Dev VM类似于:

  • Dual-Core i5 processor (with HyperThreading, so 4 virtual threads) 双核i5处理器(带超线程,4个虚拟线程)
  • 8GB RAM 8GB RAM
  • Mid Range, SATA HDD (5k or 7k2 RPM) 中档,SATA硬盘(5k或7k2 RPM)
  • Windows 7 x64 running Oracle JDK on Client mode (-client) 在客户端模式下运行Oracle JDK的 Windows 7 x64(-client)

We use Jenkins as our CI server and Maven (3.2) takes care of the build process. 我们使用Jenkins作为CI服务器,Maven(3.2)负责构建过程。 We have a Master + 2 Slaves architecture. 我们有Master + 2 Slaves架构。 All the VMs are exactly the same: 所有虚拟机完全相同:

  • 8 Xeon E5 Cores (Real cores) 8个Xeon E5核心​​(真核)
  • 8 GB RAM 8 GB RAM
  • SSD LUN serving the VMs (1.2GB/s mean throughput) 为虚拟机提供服务的SSD LUN(平均吞吐量为1.2GB / s)
  • Debian Linux 8 x64 Debian Linux 8 x64
  • Oracle JDK on Server mode 服务器模式下的Oracle JDK

Remember those tests that usually take 1:30 min to run on our Eclipse's? 还记得那些通常需要1:30分钟才能运行Eclipse的测试吗? Here on the server they take more than 15 minutes to run! 在服务器上,他们需要超过15分钟才能运行! Here's what I already tried to do (without success so far.): 这是我已经尝试过的事情(到目前为止没有成功。):

  • Set MAVEN_OPTS with fixed heap size (2GB heap), large PermGen space, tuned GC settings, /dev/urandom as random seed 将MAVEN_OPTS设置为固定堆大小(2GB堆),大型PermGen空间,调整GC设置,/ dev / urandom作为随机种子
  • Installed a 32 bits JDK to use the same Client mode we use on the Dev Machines 安装了32位JDK以使用我们在Dev Machines上使用的相同客户端模式
  • Tuned on Surefire's configuration to increase memory, tune GC, etc. (As I'm not using a forked VM to run the tests anymore I took it out because it wouldn't change anything.) 调整Surefire的配置以增加内存,调整GC等(因为我不再使用分叉的VM来运行测试,所以我把它拿出来因为它不会改变任何东西。)

Bottom line, is there any concrete reason on why Surefire's execution is s much slower than running JUnit on Eclipse? 最重要的是,为什么Surefire的执行比在Eclipse上运行JUnit要慢得多? I'm scratching my head over this for a few days now and it's really starting to annoy me! 我现在已经在这几天刮过头了,这真的开始惹恼我了! I hate it when the solution seems to be so close but yet it is so far. 当解决方案似乎如此接近但是它到目前为止,我讨厌它。

I couldn't test with Maven on my Dev machine because I couldn't allocate all the memory necessary to do it, but running chunks of classes (not the whole 1.8k tests suite) still reveals to be quite slower than running on Eclipse. 我无法在我的Dev机器上使用Maven进行测试,因为我无法分配所需的所有内存,但是运行大块的类(不是整个1.8k测试套件)仍然比在Eclipse上运行慢得多。

I understand Maven has all those phases and so on, but the difference should't be this big. 我理解Maven有所有这些阶段等等,但差别不应该是这么大。 Don't you agree? 你不同意吗?

Any input will be highly appreciated. 任何输入都将受到高度赞赏。 I can provide any more information you find necessary! 我可以提供您认为必要的更多信息!

PS: Surefire v2.17, Maven 3.2.2, JUnit 4.12, Spring Test 3.2.13 PS:Surefire v2.17,Maven 3.2.2,JUnit 4.12,Spring Test 3.2.13

Thanks a lot! 非常感谢!

UPDATE 1 更新1

I tried deactivating JaCoCo on the CI server to see if it affected the build times. 我尝试在CI服务器上停用JaCoCo以查看它是否影响了构建时间。 It doesn't. 它没有。 The execution times remain the same. 执行时间保持不变。

You can try to reproduce the remote surefire runs by running mvn test locally. 您可以尝试通过在本地运行mvn test来重现远程surefire运行。 Are you sure that you are running with the same settings, regarding forking? 对于分叉,你确定你使用相同的设置运行吗?

I know the fork settings of surefire are quite complicated and changed a bit over the time (see here for a detailed desciption: https://maven.apache.org/surefire/maven-surefire-plugin/examples/fork-options-and-parallel-execution.html ). 我知道surefire的fork设置非常复杂并且在一段时间内有所改变(详情请参阅此处: https ://maven.apache.org/surefire/maven-surefire-plugin/examples/fork-options-and -parallel-execution.html )。

If the tests get forked each time and don't reuse forks, the SpringTestRunner might spend a long time on initializing the application again and again. 如果测试每次都分叉并且不重用forks,那么SpringTestRunner可能会花费很长时间来反复初始化应用程序。

Are you sure that it's the surefire tests that really slow things down? 你确定这是真正放慢速度的可靠测试吗?

I have made some progress on this. 我在这方面取得了一些进展。 As I said above, this is a multi-modular (20+) Maven application. 如上所述,这是一个多模块(20+)Maven应用程序。 We keep all our tests separated on one module, but Surefire's configuration were being done on the parent POM, rather on the test module's POM. 我们将所有测试分开放在一个模块上,但Surefire的配置是在父POM上完成的,而不是在测试模块的POM上完成的。

After trying everything we decided to bring the test execution configuration to this module alone, skipping all the others. 在尝试了所有内容之后,我们决定单独将测试执行配置带到此模块,跳过所有其他模块。 This brought the suite execution from ~45' to 22'. 这使套件执行从大约45'到22'。 We're scratching our heads over this, and once we understand what is going on I'll post here again. 我们对此感到头疼,一旦我们了解了发生了什么,我将再次发布。

TL;DR: This image explains everything. TL; DR: 此图片解释了一切。 (off-topic, safe for work) (偏离主题,安全工作)

Thanks for all your input! 感谢您的输入!

I know this is an old thread, but maybe its still interesting: If your workload uses much stdout or stderr, surefire will create three times as big arrays as your output is, in order to save your unescaped output into them. 我知道这是一个旧线程,但它可能仍然很有趣:如果你的工作负载使用了很多stdout或stderr,那么surefire将创建三倍于你输出的大数组,以便将你的非转义输出保存到它们中。 This causes surefire to take much more time than executing the same test in eclipse or gradle. 这比使用eclipse或gradle执行相同的测试需要花费更多的时间。

I created a fork https://github.com/DaGeRe/maven-surefire and will see whether it is possible to merge this into surefire. 我创建了一个分支https://github.com/DaGeRe/maven-surefire ,并将看看是否可以将其合并到surefire中。 My personal tests went from ~1100 ms to ~370ms with the patched plugin. 使用修补的插件,我的个人测试从大约1100毫秒到大约370毫秒。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM