Более быстрые сборки Maven (Серия из 2 частей)
Сборки требуют нескольких свойств, главным из которых является воспроизводимость. Я бы счел скорость низкой в порядке приоритетов. Тем не менее, это также один из наиболее ограничивающих факторов вашего цикла выпуска: если ваша сборка занимает , вы не можете выпускать быстрее , чем каждый T . Следовательно, вы, вероятно, захотите ускорить свои сборки после достижения определенного уровня зрелости, чтобы обеспечить более частые выпуски.
В этом посте я хочу подробно рассказать о некоторых методах, которые вы можете использовать для ускорения сборки Maven. Следующий пост будет посвящен тому, как сделать то же самое внутри Docker.
Основание
Поскольку я хочу предложить методы и оценить их влияние, нам нужно хранилище образцов. Я выбрал Образцы кода Hazelcast , потому что он предоставляет достаточно большую многомодульную кодовую базу со множеством подмодулей; точная фиксация – 448febd .
Правила заключаются в следующем:
- Я запускаю команду пять раз, чтобы избежать временных проблем
- Я выполняю
mvn очищаетмежду каждым запуском, чтобы начать с пустойцелихранилище - Все зависимости и плагины уже загружены
Я сообщаю о времени, которое Maven отображает в журнале консоли:
Давайте начнем с нашей базовой линии, mvn-теста . Результаты таковы:
- 02:00 мин
- 01:57 мин
- 01:58 мин
- 01:56 мин
- 01:58 мин
Использование всех процессоров
По умолчанию Maven использует один поток. В век многоядерности это просто пустая трата времени. Можно запускать параллельные сборки с использованием нескольких потоков, установив абсолютное число или число относительно количества доступных ядер. Для получения дополнительной информации, пожалуйста, ознакомьтесь с соответствующей документацией .
Чем больше у вас подмодулей, которые не зависят друг от друга, т.е. , Maven может создавать их параллельно, тем лучше вы достигнете с помощью этой техники. Это очень хорошо вписывается в нашу кодовую базу.
Мы собираемся использовать столько потоков, сколько имеется доступных ядер. Соответствующая команда – mvn test -T1 C .
Когда команда запустится, вы должны увидеть следующее сообщение в консоли:
Using the MultiThreadedBuilder implementation with a thread count of X
- 51,487 с (Настенные часы)
- 40,322 с (Настенные часы)
- 52,468 с (Настенные часы)
- 41,862 с (Настенные часы)
- 41,699 с (Настенные часы)
Цифры намного лучше, но с большей дисперсией.
Параллельное выполнение теста
Распараллеливание – отличный метод. Мы можем сделать то же самое в отношении выполнения тестов. По умолчанию плагин Maven Surefire выполняет тесты последовательно, но его можно настроить для параллельного выполнения тестов. Пожалуйста, обратитесь к документации для получения полного набора опций.
Этот подход отлично подходит, если у вас большое количество модулей в каждом модуле. Обратите внимание, что ваши тесты должны быть независимыми друг от друга.
Мы вручную установим количество потоков:
mvn test -Dparallel=all -DperCoreThreadCount=false -DthreadCount=16 #1 #2
- Настройте Surefire для параллельного запуска обоих классов и методов
- Вручную измените количество потоков на 16
Давайте запустим его:
- 02:04 мин
- 02:03 мин
- 01:46 мин
- 01:52 мин
- 01:53 мин
Похоже, что стоимость синхронизации потоков компенсирует потенциальную выгоду от выполнения параллельных тестов.
Не в сети
Maven будет проверять, имеет ли зависимость SNAPSHOT новую “версию” при каждом запуске. Это означает дополнительные поездки по сети туда и обратно. Мы можем предотвратить эту проверку с помощью опции --offline .
В то время как вам следует избегать МОМЕНТАЛЬНОГО снимка зависимости, иногда это неизбежно, особенно во время разработки.
Команда тест mvn -o , -o является кратчайшим путем для --в автономном режиме .
- 01:46 мин
- 01:46 мин
- 01:47 мин
- 01:55 мин
- 01:44 мин
Кодовая база содержит значительное количество зависимостей SNAPSHOT ; следовательно, автономный режим значительно ускоряет сборку.
Параметры JVM
Maven сам по себе является приложением на основе Java. Это означает, что каждый запуск запускает новую JVM . JVM сначала интерпретирует байт-код и затем анализирует рабочую нагрузку и компилирует байт-код в собственный код соответственно: это означает максимальную производительность, но только через (долгое) время. Это отлично подходит для длительных процессов, а не для приложений командной строки.
Скорее всего, мы не достигнем точки максимальной производительности в контексте сборок, поскольку они относительно недолговечны, но мы все еще платим за стоимость анализа. Мы можем настроить Maven, чтобы отказаться от него, настроив соответствующие параметры JVM. Доступно несколько способов настройки JVM. Самый простой способ – создать выделенный файл конфигурации jvm.config в файле .mvn подпапка в папке проекта.
-XX:-TieredCompilation -XX:TieredStopAtLevel=1
Давайте теперь просто запустим тест mvn :
- 01:44 мин
- 01:44 мин
- 01:53 мин
- 01:53 мин
- 01:55 мин
Демон-мавен
Демон Maven является недавним дополнением к экосистеме Maven. Он черпает свое вдохновение из демона Gradle :
Gradle работает на виртуальной машине Java (JVM) и использует несколько поддерживающих библиотек, для которых требуется нетривиальное время инициализации. В результате иногда может показаться, что начинать немного медленно. Решением этой проблемы является демон Gradle: долговечный фоновый процесс, который выполняет ваши сборки намного быстрее, чем в противном случае. Мы достигаем этого, избегая дорогостоящего процесса начальной загрузки и используя кэширование, сохраняя данные о вашем проекте в памяти.
Команда Gradle рано осознала, что инструмент командной строки – не лучшее использование JVM. Чтобы исправить это, нужно всегда поддерживать фоновый процесс JVM, демон. Он действует как сервер, в то время как CLI сам играет роль клиента.
В качестве дополнительного преимущества такой длительный процесс загружает классы только один раз (если они не менялись между запусками).
После установки программного обеспечения вы можете запустить демон с помощью команды mvn вместо стандартной команды mvn . Вот результаты теста mvn :
- 33,124 с (Настенные часы)
- 33,114 с (Настенные часы)
- 34,440 с (Настенные часы)
- 32,025 с (Настенные часы)
- 29,364 с (Настенные часы)
Обратите внимание, что демон по умолчанию использует несколько потоков с количеством ядер - 1 .
Смешивание и сопоставление
Мы рассмотрели несколько способов ускорить сборку. Что, если бы мы использовали их в сочетании?
Давайте сначала попробуем использовать все техники, которые мы видели до сих пор в одном и том же прогоне:
mvnd test -Dparallel=all -DperCoreThreadCount=false -DthreadCount=16 -o #1 #2 #3 #4
- Используйте демон Maven
- Выполняйте тесты параллельно
- Не обновлять
СНИМОКзависимости - Настройте параметры JVM, как указано выше, с помощью файла
jvm.config– нет необходимости устанавливать какие-либо параметры
Команда возвращает следующие результаты:
- 27.061 с (Настенные часы)
- 24.457 с (Настенные часы)
- 24.853 с (Настенные часы)
- 25.772 с (Настенные часы)
Думая об этом, демон Maven – это длительный процесс. По этой причине разумно позволить JVM анализировать и компилировать байт-код в собственный код . Таким образом, мы можем удалить файл jvm.config и повторно выполнить приведенную выше команду. Результаты таковы:
- 23.840 с (Настенные часы)
- 26,589 с (Настенные часы)
- 22.283 с (Настенные часы)
- 23,788 с (Настенные часы)
- 22.456 с (Настенные часы)
Теперь мы можем отобразить консолидированные результаты:
| 33.12 | 106.00 | 120.00 | 104.00 | #1 (ы) | 51.00 | 128.00 | 23.84 | 27.06 |
| 33.11 | 106.00 | 117.00 | 104.00 | #2 (ы) | 40.00 | 123.00 | 26.59 | 24.46 |
| 34.44 | 107.00 | 118.00 | 113.00 | #3 (ы) | 52.00 | 106.00 | 22.28 | 24.85 |
| 32.03 | 115.00 | 116.00 | 113.00 | #4 (ы) | 42.00 | 112.00 | 23.79 | 25.77 |
| 104.00 | 118.00 | 115.00 | #5 (ы) | 42.00 | 113.00 | 22.46 | 29.36 | |
| 32.41 | 107.60 | *117.80* | 109.80 | Среднее значение (значения) | 45.40 | 116.40 | 23.79 | 25.54 |
| 2.91 | 14.64 | 1.76 | 22.96 | Отклонение | 25.44 | 63.44 | 2.38 | 1.00 |
| 85.39 | 10.20 | – | 8.00 | Выигрыш от базового (ых) уровня(ов) | 72.40 | 1.40 | 94.01 | 92.26 |
| 72.48% | 8.66% | – | 6.79% | % прироста | 61.46% | 1.19% | 79.80% | 78.32% |
Вывод
В этом посте мы рассмотрели несколько способов ускорить сборку Maven. Вот краткое изложение:
- Демон Maven : Надежная, безопасная отправная точка
- Распараллеливать сборки : Когда сборка содержит несколько модулей, независимых друг от друга
- Распараллеливать тесты : Когда проект содержит несколько тестов
- В автономном режиме : Когда проект содержит
СНИМОКзависимости и вам не нужно их обновлять - Параметры JVM : Когда вы хотите пройти лишнюю милю
Я бы посоветовал каждому пользователю начать использовать демон Maven и продолжить оптимизацию при необходимости и в зависимости от вашего проекта.
В следующем посте мы сосредоточимся на ускорении сборки Maven в контейнере.
Идти дальше:
Первоначально опубликовано на Фанат Java 3 октября рд , 2021
Более быстрые сборки Maven (Серия из 2 частей)
Оригинал: “https://dev.to/nfrankel/faster-maven-builds-17dn”