使maven构建更快的方法?

81
我有一个多模块的Java项目。Maven构建它需要大约40秒的时间。我已经尝试使用多线程构建,指定-T和-C参数以使用多少个线程和核心,但是在构建时间上没有看到任何显着的改进。
我正在使用Maven 3.2.3,并且有时需要频繁地构建我的项目。
我知道clean目标需要很长时间,但我不能省略它。
请提供建议....

编辑:
注意:在我的情况下,clean并不需要花费太多时间。它只需要1秒钟的时间完成。剩余的时间用于install。


你尝试过使用“-o”选项离线构建它吗?(假设你的依赖关系不经常更改) - TheLostMind
不好意思,我不知道-o选项。让我试一下。谢谢。 - Shubham Chaurasia
我会跳过测试。大约有30个模块。 - Shubham Chaurasia
清理需要多长时间? - khmarbaise
1
Zeroturnaround发布了一篇有趣的文章。也许你会在其中找到一些提示。 - FrVaBe
显示剩余2条评论
9个回答

77

注意:首先,据我所知,在maven中除了这里提供的所有答案之外,没有其他内置选项可用。


对于我来说,使用多线程运行maven构建可以加快构建速度。 例如:

mvn clean install -T100

-T参数是用来根据硬件配置指定使用多少线程。

下面是维基百科中的变体:

Maven 3.x 可以执行并行构建。命令如下:

  • mvn -T 4 clean install 使用 4 线程进行构建
  • mvn -T 1C clean install 每个 CPU 核心使用一个线程
  • mvn -T 1.5C clean install 每个 CPU 核心使用 1.5 个线程

执行过程是如何评估的(请参见 Maven 3 中的并行构建)?

enter image description here

图中每个节点表示多模块构建中的一个模块,“级别”仅表示到内部反应堆依赖图中第一个模块的距离。Maven 根据多模块构建中声明的模块间依赖关系计算此图。请注意,父 Maven 项目也是一个依赖项,这就解释了为什么大多数项目图的顶部只有一个节点。反应堆之外的依赖项不会影响此图。

最后,如果您想跳过测试执行,也可以使用 -DskipTests 参数。

注意:某些插件可能不兼容多线程构建器,虽然它可能能工作,但会出现以下警告信息。您可能需要查看插件文档以获得多线程支持。

[WARNING] *****************************************************************                                                                                                                                 
[WARNING] * Your build is requesting parallel execution, but project      *                                                                                                                                 
[WARNING] * contains the following plugin(s) that have goals not marked   *                                                                                                                                 
[WARNING] * as @threadSafe to support parallel building.                  *                                                                                                                                 
[WARNING] * While this /may/ work fine, please look for plugin updates    *                                                                                                                                 
[WARNING] * and/or request plugins be made thread-safe.                   *                                                                                                                                 
[WARNING] * If reporting an issue, report it against the plugin in        *                                                                                                                                 
[WARNING] * question, not against maven-core                              *                                                                                                                                 
[WARNING] *****************************************************************                                                                                                                                 
[WARNING] The following plugins are not marked @threadSafe in test-project:                                                                                                                          
[WARNING] de.dentrassi.maven:rpm:0.9.2                                                                                                                                                                      
[WARNING] Enable debug to see more precisely which goals are not marked @threadSafe.                                                                                                                        
[WARNING] *****************************************************************    

14
-DskipTests仍然会编译测试。如果您想跳过编译测试,使用-Dmaven.test.skip。 - Michael

67
在我的实际项目中:
  1. mvn clean install [INFO] 总计时间: 01:05 小时
  2. mvn clean install -DskipTests [INFO] 总计时间: 18:35 分钟
  3. mvn clean install -Dmaven.test.skip -DskipTests [INFO] 总计时间: 10:58 分钟
  4. mvn -T 1C clean install -Dmaven.test.skip -DskipTests [INFO] 总计时间: 04:00 分钟
  5. 我们可以通过添加-Dmaven.javadoc.skip=true来跳过生成javadoc,如Archmed评论所述:mvn -T 1C clean install -Dmaven.test.skip -DskipTests -Dmaven.javadoc.skip=true
  6. 不要使用*导入。在IntelliJ中,选择>分析>按名称运行检查>* imports,以查找所有* imports并进行更正。
  7. 删除您的项目中的所有未使用的imports > 在Intellij上 > 分析 > 按名称运行检查 > 未使用的imports
  8. 删除您的项目中的所有未使用的代码(类、变量、字段、参数等), 在Intellij中:分析 > 按名称运行检查 > 未使用的声明。
  9. 升级到最新的JAVA版本
  10. 我发现mvn clean这个任务在构建之前需要2分钟来清理TARGET文件夹。我创建了一个名为quickclean的新任务,并代替clean,这样就可以用mvn -T 1C quickclean install -Dmaven.test.skip -DskipTests方式执行。这个新的任务quickclean只是将build文件夹重命名为TARGET-yyyy-MM-dd-HH-mm(非常快)。所以现在,每次您进行一个新的mvn quickclean install...,都会有一个带有编译时间的文件夹。不方便的地方是,这可能会在硬盘上占用大量的空间,因此您必须有时清理所有这些目录。 因此,我创建了另一个名为:trashclean的任务,将所有这些文件夹放入垃圾箱中。 我可能每周或每月运行此任务,具体取决于我的工作情况 mvn trashclean
以下是要添加到pom.xml中的内容,如果您想使用这个概念:
<properties>
    <timestamp>${maven.build.timestamp}</timestamp>
    <maven.build.timestamp.format>yyyy-MM-dd-HH-mm</maven.build.timestamp.format>
    <trashdir>trash/target-${maven.build.timestamp}</trashdir>
</properties>

    <profile>
        <id>quickclean</id>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-antrun-plugin</artifactId>
                    <executions>
                        <execution>
                            <id>rename_target</id>
                            <phase>pre-clean</phase>
                            <goals>
                                <goal>run</goal>
                            </goals>
                            <configuration>
                                <tasks>
                                    <move todir="${trashdir}" failonerror="false">
                                        <fileset dir="target/"/>
                                    </move>
                                </tasks>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </profile>
    <profile>
        <id>trashclean</id>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-antrun-plugin</artifactId>
                    <executions>
                        <execution>
                            <id>clean_trash</id>
                            <phase>clean</phase>
                            <goals>
                                <goal>run</goal>
                            </goals>
                            <configuration>
                                <tasks>
                                    <delete dir="trash/" failonerror="false"/>
                                </tasks>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </profile>
    

为什么2和3之间会有差异? - Koray Tugay
19
2仍然可以编译测试但不运行它们,3甚至无法编译测试。在3中,“-DskipTests”是多余的,可以省略,因为结果将完全相同。 - Amedee Van Gasse
1
如果您正在进行本地构建,我还建议添加-Dmaven.javadoc.skip=true。这将跳过创建javadocs,对我的机器有很大帮助。 - Archmede
1
使用mvn -T 1C clean install -Dmaven.test.skip -DskipTests将我的构建时间从25分钟缩短到了3分53秒。谢谢! - Janet
在我的项目中(大约3000行代码,在本地机器上需要42秒的Maven构建时间),当删除“import *”并使用“-Dmaven.javadoc.skip=true”时,没有看到编译时间的差异。也许我的项目太小了...跳过测试可以将Maven构建时间缩短约10秒钟(但我希望对我的项目进行测试,因此不会禁用测试)。 - Julien Kronegg

6
您可以通过使用一些小技巧来优化构建,例如:
  1. 如果您编写了Junit测试,并且不想每次运行测试用例,可以使用-DskipTests=true
  2. 本地安装Nexus或仓库
  3. 您可以调整内存配置以达到最佳效果,例如:将此行添加到mvn.bat中:set MAVEN_OPTS=-Xmx512m -XX:MaxPermSize=256m
如需更多信息,请查看如何加速Maven构建

6
此外,固态硬盘大大加快了构建的速度。 - Vartlok
我发现了这个网址:https://dev59.com/QnPYa4cB1Zd3GeqPhEgZ - Subodh Joshi
感谢 @Vartlok,@Subodh。在我的情况下,SSD并不实用。这是一台办公电脑。 - Shubham Chaurasia
@ShubhamChaurasia 欢迎您 - Subodh Joshi
@Vartlok:有没有展示在HDD和SSD上构建速度比较的基准测试? - Gaurav
显示剩余2条评论

6
如果你有一些额外的RAM,而且不需要SSD,因为大量读写对SSD很敏感,那么你可以采用一种hacky方式。即使你禁用了一点(MacOS - 我不记得Win是否有类似的问题)。但是:

  1. 创建RAM驱动器(方法取决于您的操作系统),并将其挂载到 /Users/Username/volatile 文件夹

  2. 在MVN_HOME/lib中找到 maven-module-builder-X.X.X.jar

  3. 在JAR文件中修改 org/apache/maven/model/pom-4.0.0.xml 文件,通过修改以下内容来实现:

&lt;build>&lt;directory>/Users/Username/volatile/${project.groupId}/${project.artifactId}/${project.version}/target

  1. 从现在开始,所有项目编译都将在内存中完成。这甚至与SSD相比有所不同。

是的,这是一种hack方法,有些maven插件可能会停止工作。


5

如果使用命令行,您可以检查您的计算机有多少个核心并使用所有核心。如果您还想跳过测试,可以添加-DskipTests。例如,我有一个8核处理器:

mvn -T 8C clean install -DskipTests

39
-T xC 实际上是每个核心的线程数,所以在您的情况下,它是 8 * 8 = 64 线程。如果您想指定 maven 进程生成的确切线程数,应该使用 -T x 选项。来源:https://cwiki.apache.org/confluence/display/MAVEN/Parallel+builds+in+Maven+3 - Антон Антонов

5
除了已经提及的并行运行之外,还可以尝试使用以下 Maven 选项来加速构建: -XX:+TieredCompilation -XX:TieredStopAtLevel=1

对我来说,这些解决方案有30%的时间会减缓构建速度。 - Eduardo Yáñez Parareda

4

1
添加了这个插件后,所有的模块仍然每次都会被编译。 - tak3shi
第一次添加插件后构建时,它会分析模块,因此会正常构建。第二次构建时,如果您没有进行任何更改,应该会发现它不会构建任何内容。存储库中有一个示例项目,您可以在其中看到插件的实际效果。 - vidarmoe
好的,我找到了我的错误并解决了它。但是当我切换到另一个分支时,编译器会抱怨缺少符号,除非我重新完全编译它。 - tak3shi

1

使用Ramdisk(Windows)加速低级别操作

我的额外技巧是使用Ramdisk

  1. 创建一个2GB的Ramdisk(例如 D:
  2. 将IDE、Maven、JDK和.m2/repository安装到该Ramdisk下(D:/m2/
  3. 编辑Maven的D:/maven/conf/settings.xml以使用该Ramdisk存储库(<localRepository>D:/m2</localRepository>
  4. 将项目放入Ramdisk中
  5. 在Ramdisk中运行项目,使其临时文件夹在Ramdisk中

在我的机器上,我将

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 14.954 s (Wall Clock)
[INFO] Finished at: 2021-02-17T13:07:51+01:00
[INFO] Final Memory: 55M/642M
[INFO] ------------------------------------------------------------------------

Into

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  6.805 s (Wall Clock)
[INFO] Finished at: 2021-11-11T10:48:14Z
[INFO] ------------------------------------------------------------------------

两个结果都是高端的 (-DskipTests -T 12)

警告: 在关机前不要忘记持久化ramdisk,否则你的工作将会丢失。

看看这个怪物: 在此输入图片描述


2
我认为你不需要将IDE、JDK或Maven放在Ramdisk中。将Maven仓库和项目本身放入Ramdisk中更有意义。 - Koray Tugay
@KorayTugay 当然,项目也必须在那个RAM磁盘中。我认为这很清楚,但我编辑了答案以指出这一点。另外,-Djava.io.tmpdir=D:/temp也很重要。 - Grim
1
将IDE放入ramdisk中会有多大的差异?我认为很小,我错了吗?您是否也通过将IDE放入ramdisk中获得了显着的改进? - Koray Tugay
@KorayTugay 我有两个小原因。第一个原因是我每个项目都有一个Ramdisk-Image。它就像一个全能容器Ramdisk,其中包含了项目的JDK,与IDE运行相同的JDK,从而提供更好的调试兼容性。例如:一个项目是SWT项目,我喜欢使用netbeans。在另一个项目中,我使用eclipse。然后还有一个IntelliJ项目。第二个原因是,如果我升级了IDE,但不确定所有插件是否兼容,那么我可以通过恢复到稳定版本的Ramdisk备份来避免手动回滚IDE更新。 - Grim

0
如果您正在使用Spring Boot和Maven,并且感觉依赖项下载速度较慢,请尝试在pom.xml中进行以下设置。
<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.0</version>
        <relativePath /> 
</parent>

我发现版本2.7.0比其他版本更快地下载依赖项。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接