2015-06-10 17 views
5

Pracuję nad dość dużą aplikacją, z ~ 260 tys. LOC i około 1800 testów jednostkowych w pakiecie. Trochę tła:JUnit Tests: Dlaczego Maven (Surefire) jest o wiele wolniejszy niż działanie w Eclipse?

  1. Multi-modułowy projekt Maven
  2. Wszystkie testy wykonywane na osobnym module i JaCoCo służy do sprawdzania pokrycia.
  3. Testy są składane w niektórych pakietach, a następnie pakiety są włączone do konfiguracji Surefire.
  4. Korzystanie SpringJUnit4ClassRunner aby uruchomić testy
  5. Murowany jest obecnie skonfigurowana tak, aby używać tego samego VM budować i test (forkCount równa jeden i reuseForks równa true). Robi to jestem pewien, że używam zalety Static Context Cache sprężyny (ponowne wykorzystanie tego samego ApplicationContext na każdy test)

Kiedy prowadzimy testy na nasz rozwój VMS wykorzystaniem Oracle JDK 7u79/80 widzimy bardzo szybko testy. Na przykład dość duża klasa testowa z 50+ metodami testowymi pozwala uruchomić coś około 1: 30 m (w tym czas inicjalizacji kontekstu).

Naszym głównym Dev VM takim jak:

  • dwurdzeniowego i5 (z hiperwątkowości SO4 nici wirtualnych)
  • 8GB RAM
  • średnich, napędami (5K czy 7k2 obr./min)
  • Windows 7 x64 działa Oracle JDK tryb Client (-client)

Używamy Jenkinsa jako naszego serwera CI, a Maven (3.2) dba o proces budowania. Mamy architekturę Master + 2 Slaves. Wszystkie maszyny wirtualne są dokładnie takie same:

  • 8 Xeon E5 Rdzenie (Real rdzeni)
  • 8 GB RAM
  • SSD LUN obsługujących maszyny wirtualne (1,2 GB/s średnia przepustowość)
  • Debian Linux 8 64
  • Oracle JDK na trybie serwera

Pamiętasz te testy, które zazwyczaj 1:30 min uruchomić na naszych Eclipse? Tutaj na serwerze trwają ponad 15 minut! Oto, co już próbowałem zrobić (jak dotąd bezskutecznie.):

  • Set MAVEN_OPTS o stałej wielkości sterty (2GB sterty), dużej przestrzeni PermGen, strojonych ustawień GC/dev/urandom jako losowej nasion
  • Zainstalowałem JDK o 32 bitach, aby użyć tego samego trybu klienta, którego używamy w urządzeniach Dev.
  • Dostrojone na konfigurację Surefire w celu zwiększenia pamięci, dostrojenia GC itp. (Ponieważ nie używam rozwidlonej maszyny wirtualnej do wykonywania testów już wziąłem to, ponieważ nic by to nie zmieniło.)

Dolna linia, czy jest jakaś konkretna reaso n, dlaczego wykonanie Surefire jest znacznie wolniejsze niż uruchomienie JUnit na Eclipse?Piszę o tym przez kilka dni i to naprawdę zaczyna mnie denerwować! Nienawidzę tego, gdy rozwiązanie wydaje się tak bliskie, ale jak dotąd jest tak daleko.

Nie mogłem przetestować z Maven na mojej maszynie Dev, ponieważ nie mogłem przydzielić całej pamięci potrzebnej do tego, ale fragmenty klas (nie cały zestaw testów 1.8k) wciąż okazują się być wolniejsze niż działa na Eclipse.

Rozumiem, że Maven ma wszystkie te fazy i tak dalej, ale różnica nie powinna być tak duża. Nie zgadzasz się?

Wszelkie dane wejściowe będą bardzo cenne. Mogę podać wszelkie dodatkowe informacje, które uznasz za potrzebne!

PS: Murowany v2.17, Maven 3.2.2, JUnit 4.12, Wiosna testowa 3.2.13

Dzięki wielkie!

UPDATE 1

Starałem dezaktywacja JaCoCo na serwerze CI, aby zobaczyć, czy to dotyczy czasów budowy. Tak nie jest. Czasy wykonania pozostają takie same.

+0

Znajdź środowisko, w którym można przeprowadzać testy zarówno w trybie maven, jak i Eclipse, aby wyeliminować obszar problemowy w celu zbudowania narzędzia lub środowiska. Upewnij się, że używasz (lub nie używasz) JaCoCo w obu przypadkach, ponieważ może to znacznie spowolnić wykonywanie testów. Jeśli nic z tego nie pomoże, spróbuj porównać wydajność mavenów z Jenkinsem i bez niego. –

+0

Witam @ogondza. Dzięki za twoje wejście. Czy myślisz, że JaCoCo może tak drastycznie zwiększyć czas realizacji? Spróbuję wyłączyć agenta w Surefire i opublikuję wyniki tutaj. Wielkie dzięki! –

+0

Nigdy nie spotkałem się z tak dużą różnicą. Zwykle kilka sekund między surefire a IDE. Jeśli coś jest o wiele wolniej ... to naprawdę dziwne. Czy istnieje skaner antywirusowy na serwerze CI, który musi skanować każdy nowy plik jar? (Widziałem to na lokalnych komputerach, biorąc 40 minut zamiast 10 minut na serwerze CI) – wemu

Odpowiedz

1

Poczyniłem pewne postępy w tej sprawie. Jak już wspomniałem powyżej, jest to aplikacja wielomodułowa (20+) Maven. Wszystkie nasze testy rozdzieliliśmy na jeden moduł, ale konfiguracja Surefire była wykonywana na macierzystym POM, a raczej na module POM modułu testowego.

Po wypróbowaniu wszystkiego postanowiliśmy przenieść konfigurację wykonywania testu tylko do tego modułu, pomijając pozostałe. To spowodowało wykonanie pakietu z ~ 45 'do 22'. Chowamy się o to, a kiedy zrozumiemy, co się dzieje, opublikuję tutaj ponownie.

TL; DR: This image explains everything. (off-topic, safe for work)

Dzięki za wejście!

+1

UWAGA: ** NIE jest bezpieczne w pracy ** ... Twój obraz jest w porządku, ale niektóre z reklam po prawej stronie na pewno nie są! –

+0

@MrSpoon dzięki za ostrzeżenie)) – olyv

1

Możesz próbować odtworzyć zdalny sprawdzony ogień przez uruchomienie testu mvn na miejscu. Czy na pewno używasz tych samych ustawień dotyczących rozwidlenia?

Wiem, że ustawienia widelca surefire są dość skomplikowane i nieco zmienione w czasie (zobacz tutaj, aby zobaczyć szczegółowy opis: https://maven.apache.org/surefire/maven-surefire-plugin/examples/fork-options-and-parallel-execution.html).

Jeśli testy zostaną rozwidlone za każdym razem i nie będą ponownie używane widelców, SpringTestRunner może spędzić dużo czasu na ponownym uruchomieniu aplikacji.

Czy jesteś pewien, że to testy surefire naprawdę spowalniają działanie?

+0

Hey @ chebeutenmueller, dzięki za długie wyjaśnienie. :) Jestem pewien, że ustawienia widelca są w porządku. Ponieważ 'forkMode' był przestarzały, używam teraz kombinacji' forkCount = 0' i 'reuseForks = true'. W rzeczywistości ten drugi parametr niczego nie zmienia, ponieważ mam tylko jedną maszynę wirtualną. Jestem pewien, że konfiguracja jest w porządku, ponieważ widzę kontekst ładowany tylko raz :) Mam zainstalowaną regułę Stopwatch na moich testach, aby zmierzyć czas, więc jestem pewien, że są winni :( Dzięki! –

+0

wtyczka jaco-maven stwierdza, że ​​nie używa forkCount = 0. zobacz http://www.eclemma.org/jacoco/trunk/doc/maven.html – wemu

1

Wiem, że to stary wątek, ale może nadal jest interesujący: jeśli twój workload używa dużo stdout lub stderr, surefire stworzy trzy razy większe tablice, niż twoje wyjście, w celu zapisania do nich twoich stałych wyników. To powoduje, że zabójstwo zabiera dużo więcej czasu niż wykonanie tego samego testu w czasie zaćmienia lub gradacji.

Stworzyłem widelec https://github.com/DaGeRe/maven-surefire i zobaczę, czy można go scalić w pewny ogień. Moje osobiste testy trwały od ~ 1100 ms do ~ 370 ms z poprawioną wtyczką.

Powiązane problemy