【问题标题】:Ways to make maven build faster?使Maven构建更快的方法?
【发布时间】:2015-11-28 21:29:45
【问题描述】:

我有一个多模块 java 项目。 Maven 需要大约 40 秒来构建它。我也尝试过使用多线程构建的 maven,方法是指定 -T 和 -C 参数以不使用线程和内核。但是我没有看到我的构建时间有任何显着改善。
我正在使用 maven 3.2.3,有时我需要非常频繁地构建我的项目。
我知道干净的目标需要很多时间,但我不能忽略它。
请给点建议....

编辑:
注意:在我的情况下,清洁不需要太多时间。它在 1 秒内完成。安装正在占用其余时间。

【问题讨论】:

  • 您是否尝试过使用-o 选项离线 构建它(假设您的依赖项不经常更改)
  • 没有。我不知道 -o 选项。让我试试。谢谢。
  • @TheLostMind 对不起。没有改进。
  • 你有多少测试?你为什么经常跑步?你有多少个模块?
  • Zeroturnaround 发布了一个有趣的article。也许你会从中找到一些提示。

标签: java multithreading scala maven build


【解决方案1】:

您可以通过使用一些小的 2 技巧来优化构建,例如

  1. 如果你写过Junit Test,不想每次都运行测试用例,可以使用-DskipTests=true
  2. 本地安装 Nexus 或存储库
  3. 您可以将内存配置调整到最佳状态,例如:将此行添加到mvn.bat set MAVEN_OPTS=-Xmx512m -XX:MaxPermSize=256m

更多信息可以查看How to Speed Your Maven build

【讨论】:

  • 另外,SSD 大大加快了构建速度。
  • 谢谢@Vartlok,@Subodh。就我而言,SSD 并不实用。它是一台办公电脑
  • @ShubhamChaurasia 欢迎您
  • @Vartlok: 有没有比较 HDd 和 ssd 构建速度的基准?
【解决方案2】:

如果使用命令行,你可以检查你的机器有多少个内核并使用它们,如果你也想跳过你的测试,你可以添加-DskipTests 例如,我有 8 核处理器:

mvn -T 8C clean install -DskipTests

【讨论】:

  • -T xC 实际上是每个内核的线程数,因此在您的情况下它是 8 * 8 = 64 个线程。如果你想指定 maven 进程产生的线程的确切数量,你应该使用 -T x 选项。来源:cwiki.apache.org/confluence/display/MAVEN/…
【解决方案3】:

注意:首先是 AFAIK,除了此处的所有答案之外,maven 中没有其他内置选项。


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

mvn clean install -T100

其中 -T 用于根据您的情况指定您想要的线程数 硬件。

Below are the variants from wiki

Maven 3.x 能够执行并行构建。命令 如下:

  • mvn -T 4 clean install 使用 4 个线程构建
  • mvn -T 1C clean install 1 thread per cpu core
  • mvn -T 1.5C clean install 1.5 thread per cpu core

如何评估执行 (See Parallel builds in Maven 3)?

图中的每个节点代表多模块构建中的一个模块,“级别”仅表示到内部反应器依赖图中第一个模块的距离。 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] *****************************************************************    

【讨论】:

  • -DskipTests 仍然编译测试。如果您也想跳过编译,请使用 -Dmaven.test.skip
【解决方案4】:

如果您像我一样有一些额外的 RAM,并且不需要 SSD,那么您可以采取一种非常巧妙的方式,因为 SSD 对执行大量读写操作很敏感。即使您禁用 + 一点(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

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

  1. 从现在开始,所有项目编译都将在内存中完成。即使与 SSD 相比,它也存在差异。

是的,它的 hack 和一些 maven 插件可能会停止工作顺便说一句。

【讨论】:

    【解决方案5】:

    在我的实际项目中:

    1. mvn clean install [INFO] 总时间:01:05 h
    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 mvn -T 1C clean install -Dmaven.test.skip -DskipTests -Dmaven.javadoc.skip=true 跳过生成为 Archmed 注释 的 javadoc
    6. 不要使用 * 导入,在 IntelliJ 上,选择 > 分析 > 按名称运行检查 > * 导入,以查找所有 * 导入并更正它。
    7. 删除项目中的所有未使用的导入 > 在 Intellij > 分析 > 按名称运行检查 > 未使用的导入
    8. 删除所有未使用的代码(类、变量、字段、参数等),在 Intellij 上:分析 > 按名称运行检查 > 未使用的声明。
    9. 升级到最新的 JAVA 版本
    10. 我发现任务 mvn clean 在构建之前需要 2 分钟来清理 TARGET 文件夹。我确实创建了一个名为 quickclean 的新任务,并且我正在使用它而不是 clean,这种方式 mvn -T 1C quickclean install -Dmaven.test.skip -DskipTests 。这个新任务 quickclean 只是重命名构建文件夹从 TARGET 到 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有区别?
    • 2 仍然编译测试但不运行它们,3 甚至不编译测试。 -DskipTests 在 3 中是多余的,可以省略,它会产生相同的结果。
    • 如果您正在为本地构建进行编译,我还建议您添加 -Dmaven.javadoc.skip=true。这将跳过创建 javadocs,这对我的机器有很大帮助
    • 使用 mvn -T 1C clean install -Dmaven.test.skip -DskipTests 将我的构建时间从 25 分钟减少到 3:53 分钟。谢谢!
    【解决方案6】:

    除了许多人已经提到的并行运行之外,试试这些 maven 选项可以加快构建速度 -XX:+TieredCompilation -XX:TieredStopAtLevel=1

    【讨论】:

      【解决方案7】:

      使用 Ramdisk (Windows) 的低级速度

      我的另一个技巧是使用 ramdisk

      1. 创建一个 2GB 的 Ramdisk(例如 D:
      2. 将 IDE、Maven、JDK 和 .m2/repository 安装到该 Ramdisk (D:/m2/)。
      3. 编辑 Maven 的 D:/maven/conf/settings.xml 以使用该 Ramdisked 存储库 (&lt;localRepository&gt;D:/m2&lt;/localRepository&gt;)
      4. 将项目放入 ramdisk。
      5. 运行项目,其临时文件夹位于 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] ------------------------------------------------------------------------
      

      进入

      [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,否则您的工作将丢失。

      看看这个野兽:

      【讨论】:

      • 我认为您不需要在 Ramdisk 中使用 IDE、JDK 或 Maven。将 maven repo 和项目本身放在 ramdisk 中会更有意义。
      • @KorayTugay Naturaly 该项目也必须在该虚拟磁盘中。我认为这很清楚,但我编辑了答案以指出这一点。 -Djava.io.tmpdir=D:/temp 也很重要。
      • 将 IDE 放入 ramdisk 有多大不同?我想的很少,我错了吗?通过在 ramdisk 中也使用 IDE,您是否体验到了很大的改进?
      • @KorayTugay 我有两个次要原因。第一个原因是我每个项目都有一个 Ramdisk-Image。它就像一个多合一容器内存盘,项目的 JDK 运行与 IDE 完全相同的 JDK,从而提供更好的调试兼容性。举个例子:一个项目是一个 SWT 项目,我更喜欢使用 netbeans。在另一个项目中,我使用 eclipse。然后是一个 IntelliJ 项目。第二个原因是,如果我升级了 IDE,但不确定我的所有插件是否兼容,而不是手动回滚 IDE 更新,我有一个 ramdisk 备份来恢复到稳定版本。
      猜你喜欢
      • 1970-01-01
      • 2011-10-06
      • 2015-01-09
      • 2020-06-09
      • 2020-12-20
      • 2011-10-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多