原文發(fā)布于:https://nosugarcoffee.github.io/Mvnd%20vs%20Maven
介紹
Mvnd 是一個(gè)致力于提升 maven 構(gòu)建速度的項(xiàng)目。它不是一個(gè)全新的產(chǎn)物洛退,而是內(nèi)置 maven,并且整合 Gradle 和 Takari 中的優(yōu)勢(shì)技術(shù)。那么它借鑒了什么篓像?對(duì)比 maven 優(yōu)勢(shì)是否明顯谆级?適合使用在哪些場(chǎng)景温治?本文帶你一探究竟。
基本使用
安裝
Mvnd 0.7.1 運(yùn)行依賴(lài) jdk 11, 如不滿足有以下提示:
org/mvndaemon/mvnd/client/DefaultClient has been compiled by a more recent version of the Java Runtime (class file version 55.0)
推薦使用 jabba或 asdf 管理 java 多版本橄登。
觀察
執(zhí)行 mvnd
命令即可觀察到啟動(dòng)了 daemon 進(jìn)程,同時(shí)該命令也充當(dāng) client 與 daemon service 交互讥此。
執(zhí)行 mvnd --status
查看 daemon 狀態(tài)拢锹,如下展示的是一個(gè)空閑狀態(tài)的 daemon:
liangliangdai@liangliangdai-VirtualBox:~/jacoco$ /home/liangliangdai/Downloads/mvnd-0.7.1-linux-amd64/bin/mvnd --status
ID PID Address Status RSS Last activity Java home
88a359ee 69068 inet:/127.0.0.1:36633 Idle 132m 2021-12-30T12:20:43.405 /home/liangliangdai/.jabba/jdk/openjdk@1.11.0
執(zhí)行 mvnd --stop
停止 daemon。
實(shí)例測(cè)試
事先說(shuō)明
- 均基于 4 core linux 虛擬機(jī)
- 均設(shè)置 Jvm args
-Xms128M
Xmx2048M
- Mvnd 默認(rèn)開(kāi)啟并行構(gòu)建萄喳,線程數(shù)量為
Math.max(Runtime.getRuntime().availableProcessors() - 1, 1)
卒稳,為了保持一致,并行參數(shù)統(tǒng)一設(shè)置-T 4
他巨,-T 4
表示開(kāi)啟并行構(gòu)建的線程數(shù)為 4 個(gè)
Jacoco | 20 + modules
mvn clean verify
執(zhí)行成功:
[INFO] Reactor Summary for root 0.8.6:
[INFO]
[INFO] JaCoCo ............................................. SUCCESS [ 2.454 s]
[INFO] JaCoCo :: Core ..................................... SUCCESS [ 10.961 s]
[INFO] JaCoCo :: Report ................................... SUCCESS [ 5.012 s]
[INFO] JaCoCo :: Agent RT ................................. SUCCESS [ 2.425 s]
[INFO] JaCoCo :: Agent .................................... SUCCESS [ 3.108 s]
[INFO] JaCoCo :: Ant ...................................... SUCCESS [ 3.423 s]
[INFO] JaCoCo :: Command Line Interface ................... SUCCESS [ 3.536 s]
[INFO] JaCoCo :: Examples ................................. SUCCESS [ 3.183 s]
[INFO] JaCoCo :: Maven Plugin ............................. SUCCESS [ 6.747 s]
[INFO] JaCoCo :: Tests .................................... SUCCESS [ 0.192 s]
[INFO] JaCoCo :: Test :: Core ............................. SUCCESS [ 6.984 s]
[INFO] JaCoCo :: Test :: Core :: Validation ............... SUCCESS [ 0.049 s]
[INFO] JaCoCo :: Test :: Core :: Validation Java 5 ........ SUCCESS [ 3.031 s]
[INFO] JaCoCo :: Test :: Core :: Validation Kotlin ........ SUCCESS [ 11.635 s]
[INFO] JaCoCo :: Test :: Core :: Validation Java 7 ........ SUCCESS [ 2.744 s]
[INFO] JaCoCo :: Test :: Core :: Validation Java 8 ........ SUCCESS [ 2.680 s]
[INFO] JaCoCo :: Test :: Core :: Validation Groovy ........ SUCCESS [ 4.787 s]
[INFO] JaCoCo :: Test :: Core :: Validation Scala ......... SUCCESS [ 10.767 s]
[INFO] JaCoCo :: Test :: Report ........................... SUCCESS [ 5.021 s]
[INFO] JaCoCo :: Test :: Agent RT ......................... SUCCESS [ 3.188 s]
[INFO] JaCoCo :: Test :: Agent ............................ SUCCESS [ 2.288 s]
[INFO] JaCoCo :: Test :: Ant .............................. SUCCESS [ 8.807 s]
[INFO] JaCoCo :: Test :: Command Line Interface ........... SUCCESS [ 4.286 s]
[INFO] JaCoCo :: Test :: Examples ......................... SUCCESS [ 17.863 s]
[INFO] JaCoCo :: Test :: Maven Plugin ..................... SUCCESS [01:59 min]
[INFO] JaCoCo :: Documentation ............................ SUCCESS [ 11.561 s]
[INFO] JaCoCo :: Distribution ............................. SUCCESS [ 1.810 s]
[INFO] root ............................................... SUCCESS [ 0.034 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 04:18 min
mvnd clean verify
執(zhí)行失敗:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-plugin-plugin:3.6.0:report (report) on project jacoco-maven-plugin: Execution report of goal org.apache.maven.plugins:maven-plugin-plugin:3.6.0:report failed: A required class was missing while executing org.apache.maven.plugins:maven-plugin-plugin:3.6.0:report: org/jacoco/report/check/IViolationsOutput
[ERROR] -----------------------------------------------------
[ERROR] realm = plugin>org.apache.maven.plugins:maven-plugin-plugin:3.6.0
[ERROR] strategy = org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy
[ERROR] urls[0] = file:/home/liangliangdai/.m2/repository/org/apache/maven/plugins/maven-plugin-plugin/3.6.0/maven-plugin-plugin-3.6.0.jar
[ERROR] urls[1] = file:/home/liangliangdai/.m2/repository/org/ow2/asm/asm/7.1/asm-7.1.jar
[ERROR] urls[2] = file:/home/liangliangdai/.m2/repository/org/sonatype/aether/aether-util/1.7/aether-util-1.7.jar
[ERROR] urls[3] = file:/home/liangliangdai/.m2/repository/org/sonatype/plexus/plexus-sec-dispatcher/1.3/plexus-sec-dispatcher-1.3.jar
[ERROR] urls[4] = file:/home/liangliangdai/.m2/repository/org/sonatype/plexus/plexus-cipher/1.4/plexus-cipher-1.4.jar
[ERROR] urls[5] = file:/home/liangliangdai/.m2/repository/org/codehaus/plexus/plexus-interpolation/1.14/plexus-interpolation-1.14.jar
[ERROR] urls[6] = file:/home/liangliangdai/.m2/repository/org/sonatype/sisu/sisu-inject-bean/1.4.2/sisu-inject-bean-1.4.2.jar
[ERROR] urls[7] = file:/home/liangliangdai/.m2/repository/org/sonatype/sisu/sisu-guice/2.1.7/sisu-guice-2.1.7-noaop.jar
[ERROR] urls[8] = file:/home/liangliangdai/.m2/repository/org/codehaus/plexus/plexus-component-annotations/1.5.5/plexus-component-annotations-1.5.5.jar
[ERROR] urls[9] = file:/home/liangliangdai/.m2/repository/org/apache/maven/plugin-tools/maven-plugin-tools-api/3.6.0/maven-plugin-tools-api-3.6.0.jar
[ERROR] urls[10] = file:/home/liangliangdai/.m2/repository/org/apache/maven/plugin-tools/maven-plugin-tools-generators/3.6.0/maven-plugin-tools-generators-3.6.0.jar
[ERROR] urls[11] = file:/home/liangliangdai/.m2/repository/org/ow2/asm/asm-commons/7.0/asm-commons-7.0.jar
[ERROR] urls[12] = file:/home/liangliangdai/.m2/repository/org/ow2/asm/asm-tree/7.0/asm-tree-7.0.jar
[ERROR] urls[13] = file:/home/liangliangdai/.m2/repository/org/ow2/asm/asm-analysis/7.0/asm-analysis-7.0.jar
[ERROR] urls[14] = file:/home/liangliangdai/.m2/repository/net/sf/jtidy/jtidy/r938/jtidy-r938.jar
[ERROR] urls[15] = file:/home/liangliangdai/.m2/repository/org/apache/maven/plugin-tools/maven-plugin-tools-java/3.6.0/maven-plugin-tools-java-3.6.0.jar
[ERROR] urls[16] = file:/home/liangliangdai/.m2/repository/com/thoughtworks/qdox/qdox/2.0-M5/qdox-2.0-M5.jar
[ERROR] urls[17] = file:/home/liangliangdai/.m2/repository/org/apache/maven/plugin-tools/maven-plugin-tools-annotations/3.6.0/maven-plugin-tools-annotations-3.6.0.jar
[ERROR] urls[18] = file:/home/liangliangdai/.m2/repository/org/codehaus/plexus/plexus-archiver/3.6.0/plexus-archiver-3.6.0.jar
[ERROR] urls[19] = file:/home/liangliangdai/.m2/repository/org/codehaus/plexus/plexus-io/3.0.1/plexus-io-3.0.1.jar
[ERROR] urls[20] = file:/home/liangliangdai/.m2/repository/commons-io/commons-io/2.6/commons-io-2.6.jar
[ERROR] urls[21] = file:/home/liangliangdai/.m2/repository/org/apache/commons/commons-compress/1.16.1/commons-compress-1.16.1.jar
[ERROR] urls[22] = file:/home/liangliangdai/.m2/repository/org/objenesis/objenesis/2.6/objenesis-2.6.jar
[ERROR] urls[23] = file:/home/liangliangdai/.m2/repository/org/iq80/snappy/snappy/0.4/snappy-0.4.jar
[ERROR] urls[24] = file:/home/liangliangdai/.m2/repository/org/tukaani/xz/1.8/xz-1.8.jar
[ERROR] urls[25] = file:/home/liangliangdai/.m2/repository/org/apache/maven/plugin-tools/maven-plugin-annotations/3.6.0/maven-plugin-annotations-3.6.0.jar
[ERROR] urls[26] = file:/home/liangliangdai/.m2/repository/org/apache/maven/doxia/doxia-sink-api/1.4/doxia-sink-api-1.4.jar
[ERROR] urls[27] = file:/home/liangliangdai/.m2/repository/org/apache/maven/doxia/doxia-logging-api/1.4/doxia-logging-api-1.4.jar
[ERROR] urls[28] = file:/home/liangliangdai/.m2/repository/org/apache/maven/doxia/doxia-site-renderer/1.4/doxia-site-renderer-1.4.jar
[ERROR] urls[29] = file:/home/liangliangdai/.m2/repository/org/apache/maven/doxia/doxia-core/1.4/doxia-core-1.4.jar
[ERROR] urls[30] = file:/home/liangliangdai/.m2/repository/xerces/xercesImpl/2.9.1/xercesImpl-2.9.1.jar
[ERROR] urls[31] = file:/home/liangliangdai/.m2/repository/xml-apis/xml-apis/1.3.04/xml-apis-1.3.04.jar
[ERROR] urls[32] = file:/home/liangliangdai/.m2/repository/org/apache/httpcomponents/httpclient/4.0.2/httpclient-4.0.2.jar
[ERROR] urls[33] = file:/home/liangliangdai/.m2/repository/commons-codec/commons-codec/1.3/commons-codec-1.3.jar
[ERROR] urls[34] = file:/home/liangliangdai/.m2/repository/org/apache/httpcomponents/httpcore/4.0.1/httpcore-4.0.1.jar
[ERROR] urls[35] = file:/home/liangliangdai/.m2/repository/org/apache/maven/doxia/doxia-decoration-model/1.4/doxia-decoration-model-1.4.jar
[ERROR] urls[36] = file:/home/liangliangdai/.m2/repository/org/apache/maven/doxia/doxia-module-xhtml/1.4/doxia-module-xhtml-1.4.jar
[ERROR] urls[37] = file:/home/liangliangdai/.m2/repository/org/apache/maven/doxia/doxia-module-fml/1.4/doxia-module-fml-1.4.jar
[ERROR] urls[38] = file:/home/liangliangdai/.m2/repository/org/codehaus/plexus/plexus-i18n/1.0-beta-7/plexus-i18n-1.0-beta-7.jar
[ERROR] urls[39] = file:/home/liangliangdai/.m2/repository/org/apache/velocity/velocity-tools/2.0/velocity-tools-2.0.jar
[ERROR] urls[40] = file:/home/liangliangdai/.m2/repository/commons-beanutils/commons-beanutils/1.7.0/commons-beanutils-1.7.0.jar
[ERROR] urls[41] = file:/home/liangliangdai/.m2/repository/commons-digester/commons-digester/1.8/commons-digester-1.8.jar
[ERROR] urls[42] = file:/home/liangliangdai/.m2/repository/commons-chain/commons-chain/1.1/commons-chain-1.1.jar
[ERROR] urls[43] = file:/home/liangliangdai/.m2/repository/commons-logging/commons-logging/1.1/commons-logging-1.1.jar
[ERROR] urls[44] = file:/home/liangliangdai/.m2/repository/javax/servlet/servlet-api/2.3/servlet-api-2.3.jar
[ERROR] urls[45] = file:/home/liangliangdai/.m2/repository/dom4j/dom4j/1.1/dom4j-1.1.jar
[ERROR] urls[46] = file:/home/liangliangdai/.m2/repository/oro/oro/2.0.8/oro-2.0.8.jar
[ERROR] urls[47] = file:/home/liangliangdai/.m2/repository/sslext/sslext/1.2-0/sslext-1.2-0.jar
[ERROR] urls[48] = file:/home/liangliangdai/.m2/repository/org/apache/struts/struts-core/1.3.8/struts-core-1.3.8.jar
[ERROR] urls[49] = file:/home/liangliangdai/.m2/repository/antlr/antlr/2.7.2/antlr-2.7.2.jar
[ERROR] urls[50] = file:/home/liangliangdai/.m2/repository/org/apache/struts/struts-taglib/1.3.8/struts-taglib-1.3.8.jar
[ERROR] urls[51] = file:/home/liangliangdai/.m2/repository/org/apache/struts/struts-tiles/1.3.8/struts-tiles-1.3.8.jar
[ERROR] urls[52] = file:/home/liangliangdai/.m2/repository/commons-collections/commons-collections/3.2.1/commons-collections-3.2.1.jar
[ERROR] urls[53] = file:/home/liangliangdai/.m2/repository/org/apache/maven/reporting/maven-reporting-impl/2.3/maven-reporting-impl-2.3.jar
[ERROR] urls[54] = file:/home/liangliangdai/.m2/repository/backport-util-concurrent/backport-util-concurrent/3.1/backport-util-concurrent-3.1.jar
[ERROR] urls[55] = file:/home/liangliangdai/.m2/repository/org/apache/maven/shared/maven-shared-utils/0.6/maven-shared-utils-0.6.jar
[ERROR] urls[56] = file:/home/liangliangdai/.m2/repository/com/google/code/findbugs/jsr305/2.0.1/jsr305-2.0.1.jar
[ERROR] urls[57] = file:/home/liangliangdai/.m2/repository/commons-validator/commons-validator/1.3.1/commons-validator-1.3.1.jar
[ERROR] urls[58] = file:/home/liangliangdai/.m2/repository/org/apache/maven/reporting/maven-reporting-api/3.0/maven-reporting-api-3.0.jar
[ERROR] urls[59] = file:/home/liangliangdai/.m2/repository/org/codehaus/plexus/plexus-utils/3.0.20/plexus-utils-3.0.20.jar
[ERROR] urls[60] = file:/home/liangliangdai/.m2/repository/org/codehaus/plexus/plexus-velocity/1.1.8/plexus-velocity-1.1.8.jar
[ERROR] urls[61] = file:/home/liangliangdai/.m2/repository/junit/junit/3.8.1/junit-3.8.1.jar
[ERROR] urls[62] = file:/home/liangliangdai/.m2/repository/org/apache/maven/surefire/maven-surefire-common/2.19.1/maven-surefire-common-2.19.1.jar
[ERROR] urls[63] = file:/home/liangliangdai/.m2/repository/org/apache/maven/surefire/surefire-api/2.19.1/surefire-api-2.19.1.jar
[ERROR] urls[64] = file:/home/liangliangdai/.m2/repository/org/apache/maven/surefire/surefire-booter/2.19.1/surefire-booter-2.19.1.jar
[ERROR] urls[65] = file:/home/liangliangdai/.m2/repository/org/apache/commons/commons-lang3/3.1/commons-lang3-3.1.jar
[ERROR] urls[66] = file:/home/liangliangdai/.m2/repository/org/apache/velocity/velocity/1.7/velocity-1.7.jar
[ERROR] urls[67] = file:/home/liangliangdai/.m2/repository/commons-lang/commons-lang/2.4/commons-lang-2.4.jar
[ERROR] Number of foreign imports: 1
[ERROR] import: Entry[import from realm ClassRealm[maven.api, parent: null]]
[ERROR]
[ERROR] -----------------------------------------------------
[ERROR] : org.jacoco.report.check.IViolationsOutput
[ERROR] -> [Help 1]
以上得出使用 mvnd 構(gòu)建可能導(dǎo)致失敗充坑。
Sonar-java | 10 ~ modules
mvn-single
: maven3 - single thread build - mvn clean verify
次數(shù) | 時(shí)間 |
---|---|
1 | 02:27 min |
2 | 02:28 min |
mvn-multi
: maven3 - multi thread build - mvn clean verify -T 4
Maven3 的 并行構(gòu)建。
次數(shù) | 時(shí)間 |
---|---|
1 | 02:18 min |
2 | 02:23 min |
mvnd-multi-cold
: mvnd - multi thread build - "cold" daemon - mvnd clean verify -T 4
"cold" daemon 是指使用 mvnd --stop
停止 daemon 后進(jìn)行構(gòu)建染突。
次數(shù) | 時(shí)間 |
---|---|
1 | 02:13 min |
2 | 02:08 min |
mvnd-multi-hot
: mvnd - multi thread build - "hot" daemon - mvnd clean verify -T 4
"hot" daemon 是指 daemon 已經(jīng)構(gòu)建過(guò)幾次捻爷。
次數(shù) | 時(shí)間 |
---|---|
1 | 01:56 min |
2 | 01:51 min |
從 mvnd-multi-hot
與 mvn-single
可得最優(yōu)情況下 mvnd 大約可以為此項(xiàng)目提高 20% 的構(gòu)建速度。
結(jié)論及分析
C/S 和 smart builder 是其快的原因
Mvnd 借鑒 Gradle daemon 的思想份企,使 daemon 常駐后臺(tái)也榄,構(gòu)建請(qǐng)求由 GraalVM client 轉(zhuǎn)發(fā),得益于 classloader cache 和 JIT 的特性, 下次構(gòu)建無(wú)需重復(fù)加載已緩存的 plugin classes司志,同時(shí)熱點(diǎn)代碼信息也被記錄手蝎,更快甚至直接 JIT不像 maven 每次構(gòu)建都需要新建 jvm榕莺,故 C/S 架構(gòu)是 mvnd 構(gòu)建快的關(guān)鍵因素之一。
mvnd-multi-hot
優(yōu)于mvnd-multi-cold
的結(jié)果棵介,很好的體現(xiàn)了 daemon 的優(yōu)勢(shì)钉鸯。
Mvnd 借鑒 Takari smart builder 的技術(shù),相比與 maven3 并行構(gòu)建模型更優(yōu)邮辽。此為 mvnd 構(gòu)建快的另一關(guān)鍵因素唠雕。下圖展示了 maven 3 和 mvnd 并行構(gòu)建模型的區(qū)別:
mvnd-multi-cold
,mvn-multi
雙方都是并行構(gòu)建且從 "cold" 啟動(dòng)吨述,mvnd 略?xún)?yōu)岩睁,故優(yōu)勢(shì)很可能來(lái)自 smart build,當(dāng)然樣本數(shù)太少揣云,不足以下定論捕儒,讀者可自行測(cè)試。
Mvnd 適合本地構(gòu)建邓夕,CI 有一定潛力
當(dāng)今主流的 CI 大多基于容器刘莹,目前 mvnd daemon 只支持來(lái)自本機(jī) client 的構(gòu)建請(qǐng)求,即各個(gè) job 所屬的容器只能利用自身啟動(dòng)的 daemon, 假如容器內(nèi)只進(jìn)行單次構(gòu)建的話那就沒(méi)那么大優(yōu)勢(shì)了焚刚,而本地構(gòu)建無(wú)此限制点弯,社區(qū)有類(lèi)似的 討論。
mvnd is primarily designed for iterative development on a developer workstation. I think it is worth trying as a drop-in replacement of stock Maven. In case of issues, the users are invited to report them in the project. I see little potential for mvnd in the area of continuous integration (CI).
來(lái)源: Conversation with Peter Palaga and Guillaume Nodet
并行構(gòu)建不能無(wú)腦使用
請(qǐng)自行閱讀 并行構(gòu)建可能帶來(lái)的問(wèn)題 以及作者向社區(qū)反饋的 問(wèn)題矿咕。