如何加速 Maven 構建
1. 概述
在本教程中,我們將學習如何加快 Maven 構建速度。我們將介紹各種優化構建時間的技術,並評論它們的優點和缺點。
2. 一般建議
在進行任何優化嘗試之前,讓我們回想一下,使用正確的 Maven 階段可以為我們節省大量時間。當我們只需要編譯代碼時,為什麼要運行完整install
並污染我們的本地存儲庫?
另一方面,在多模塊項目中,可以僅重建已更改的模塊以及依賴它們的模塊。例如,如果我們僅在module1
和module2
中進行更改,我們可以運行:
$ mvn clean install -pl module1,module2 -am
3. 使用多線程
默認情況下,Maven 構建在單個線程中順序運行。然而,如今所有計算機都有多個核心。讓我們利用這一點來使用-T
選項並並行構建我們的模塊:
$ mvn clean install -T 1C
-
-T 1C
表示 Maven 將為每個可用核心使用一個線程。 -
-T 4
將強制 Maven 使用四個線程。 -
-T auto
會讓 Maven 確定要使用的線程數。
最後但並非最不重要的一點是,Maven Reactor 確保所有相互依賴的模塊都將按順序運行。
4. 優化測試
測試是軟件開發的重要組成部分。然而,減少運行它們會花費很多時間。
4.1.並行運行測試
默認情況下,Surefire 插件按順序運行單元測試。但是,我們可以將其配置為並行運行它們。例如,要並行運行所有測試套件並為每個可用核心使用一個線程,我們將運行:
mvn clean install -Dparallel=all -DperCoreThreadCount=true
但是,如果我們的項目中沒有大量單元測試,並行化的開銷成本可能會抵消速度增益。
4.2.跳過測試執行
有時我們不需要在本地環境中運行測試。 Maven -DskipTests
選項會跳過測試執行,同時仍然編譯測試文件夾:
$ mvn clean install -DskipTests
在經過高度測試的項目中,在不需要測試時跳過測試可以節省我們的時間!
4.3.跳過測試編譯
此外,我們可以使用-Dmaven.test.skip=true
選項跳過測試執行,甚至不編譯它們:
$ mvn clean install -Dmaven.test.skip=true
此方法進一步減少了總構建時間。
5. 優化JVM參數
默認情況下,HotSpot JVM 使用分層編譯:它使用客戶端和服務器編譯器來優化 Java 字節碼。此功能優化了服務器上的長期進程。然而,構建是一系列短暫的過程。因此,我們使用以下 JVM 參數:
-
-XX:-TieredCompilation
:JVM不會使用分層編譯 -
-XX:TieredStopAtLevel=1
:JVM 將僅使用客戶端編譯器
我們可以通過創建包含以下內容的.mvn/jvm.config
文件來讓 Maven 使用這些選項:
-XX:-TieredCompilation -XX:TieredStopAtLevel=1
實際上,Maven 使用緩存和增量構建技術來避免重新編譯未更改的代碼。因此,Maven 需要編譯的新代碼越多,這種技術就越高效。
6. 離線
Maven 在構建過程中會多次往返服務器,例如,用於依賴項解析和插件下載。特別是,它每次都會檢查新的快照更新。我們可以通過進入離線模式來避免這種情況:
$ mvn clean install -o
顯然,當我們需要更新一些依賴項時,我們不能使用離線模式。
7. 識別瓶頸
如果以前的技術不能幫助我們將構建時間恢復到可接受的水平,我們可以藉助分析器對構建進行故障排除。首先,讓我們創建一個新的 Maven 項目。然後,我們將按照Maven Profiler項目的 GitHub 上的說明進行安裝。最後,我們需要在pom.xml
中添加依賴項:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-profiler-plugin</artifactId>
<version>1.7</version>
</plugin>
</plugins>
</build>
我們現在可以通過啟動命令來使用它來更深入地了解我們的構建時間:
$ mvn clean install -Dprofile
構建完成後,我們可以在.profiler
文件夾中找到 HTML 文本的報告。我們來看看:
正如我們所看到的,分析器列出了所有插件的執行並記錄了它們所花費的時間。第二部分列出了下載的工件。這些信息可以幫助我們識別那些需要很長時間才能運行但在目標環境中幾乎沒有價值的插件。
8. 使用 Maven 配置文件
一旦發現瓶頸,我們就可以使用 Maven 配置文件按需跳過它們並節省時間。例如,執行集成測試通常很長。此外,每次都在本地環境中運行它們是沒有用的。
讓我們在pom.xml
中添加failsafe
插件配置:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>3.1.2</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
我們現在可以添加一個配置文件來跳過它們:
<profiles>
<profile>
<id>skipITs</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
由於覆蓋了配置,激活了skipITs
配置文件,現在可以跳過集成測試:
$ mvn clean install -PskipITs
9. 使用 Maven 守護進程
Maven 守護進程旨在提高 Maven 構建的速度。該守護進程是一個長期存在的後台進程,即使在構建完成後仍保持活動狀態。它通過將基本組件保留在內存中來減少構建開銷,通過避免重複的啟動和初始化過程來實現更快的項目構建。要安裝它,我們可以按照項目的GitHub頁面上的說明進行操作。現在讓我們使用它來啟動構建:
$ mvnd clean install
如果需要啟動守護進程,則構建時間會稍長一些。最後但並非最不重要的一點是,我們可以將前面的技術與 Maven 守護進程結合起來。例如,我們可以通過守護進程構建並跳過測試:
$ mvnd clean install -Dmaven.test.skip=true
儘管如此,我們還是要指出,由於 Maven 守護進程是一個長期存在的進程,因此像我們之前那樣設置 JVM 參數可能弊大於利。
10. 結論
在本文中,我們展示了使用 Maven 縮短構建時間的各種技術。簡而言之,我們應該決定開始使用 Maven 守護進程。然後,當我們不需要運行測試時,請記住跳過它們。我們還可以分析構建並使用 Maven 配置文件來排除耗時的低價值任務。如果這些還不夠,我們可以嘗試本文中描述的其他技術。
與往常一樣,代碼可以在 GitHub 上獲取。