Java项目编译加速那些事

互联网技术团队的Java项目技术栈都类似,想必大家都会遇到打包慢的情况(特别是大项目),此文分享引擎开发团队积累的一些编译优化的经验,供大家参考与交流。

此文是跳过问题分析过程,直接给出最佳实践。下面的步骤,可以选择性、组合使用。

流水线编译优化最佳实践

mvn参数优化

mvn clean package -U --batch-mode -T 1C --no-transfer-progress -Dmaven.test.skip=true

下面是DSP工程的参数示例,因该工程中包含多个服务,但流水线只需要一个服务,故可通过 --projects 指定。

css 复制代码
mvn --batch-mode -T 1C --no-transfer-progress --projects ad-show-performance-service --also-make clean package -U -Dmaven.test.skip=true -Djacoco.skip=true

优化效果:DSP编译时间从4分钟下降到1分10秒左右。

开发、测试环境使用包部署

使用包部署而不是镜像部署,则编译任务可保持最简(删除打包镜像步骤,打包镜像很慢)。

优化效果:节省镜像打包、上传的过程,大概2分钟。

替换maven插件

原来使用maven-dependency-plugin + maven-assembly-plugin + maven-jar-plugin

xml 复制代码
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <version>3.6.0</version>
            <configuration>
                <outputDirectory>${project.build.directory}/libs</outputDirectory>
            </configuration>
            <executions>
                <execution>
                    <id>copy-dependencies</id>
                    <phase>package</phase>
                    <goals>
                        <goal>copy-dependencies</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <!-- 打包 -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>3.3.0</version>
            <configuration>
                <archive>
                    <manifest>
                        <Main-Class>com.heytap.ad.show.performance.BootstrapApplication</Main-Class>
                        <addClasspath>true</addClasspath>
                        <classpathPrefix>libs</classpathPrefix>
                        <useUniqueVersions>false</useUniqueVersions>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>3.6.0</version>
            <configuration>
                <appendAssemblyId>false</appendAssemblyId>
                <finalName>${project.artifactId}-${maven.build.timestamp}</finalName>
                <tarLongFileMode>gnu</tarLongFileMode>
                <descriptors>
                    <descriptor>src/main/assembly/assembly.xml</descriptor>
                </descriptors>
            </configuration>
            <executions>
                <execution>
                    <id>make-assembly</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

可替换成:maven-jar-plugin + spring-boot-maven-plugin(注意,不只是简单替换掉插件,还需要正确处理好spring-boot的依赖,以及流水线的编译任务,见:编译优化技术方案

xml 复制代码
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <configuration>
                <archive>
                    <manifest>
                        <Main-Class>com.heytap.ad.show.performance.BootstrapApplication</Main-Class>
                        <addClasspath>true</addClasspath>
                        <classpathPrefix>libs</classpathPrefix>
                        <useUniqueVersions>false</useUniqueVersions>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

注意:这个优化操作成本比较大,且对于流水线Linux环境来说,有了前面2个优化步骤后,这一步的额外效果不是很明显(windows环境下效果比较明显),故建议新项目使用。

优化效果:在没有做mvn参数优化的情况下,编译时间由4分钟优化到1分10秒左右。但在做了mvn参数优化的情况下,进一步的优化不明显,大概能进一步节省10多秒时间。

windows本地编译加速

如果你是一次过的选手,写完代码直接提交的,可以跳过此小节。

如果你需要本地编译,如:

  1. 需要确保代码能编译成功,避免提交之后影响流水线及其他同学的工作;
  2. 需要在本地起服务进行调试。

那么编译加速优化后,能节省日常开发大量的时间。

优化效果

DSP项目,没有任何优化前,本地编译大概4分钟。

使用mvn参数优化后,耗时大概为2分钟:

使用 mvnd 后,最短编译时间约为1分10秒(下面能看出第2次执行比第1次快):

再替换maven插件后,最短编译时间约为30秒。

mvn参数优化

同上面的流水线编译优化。但 --batch-mode 参数效果不太明显。

替换maven插件

同上面的流水线编译优化。但考虑到此操作成本比较大,建议在新项目中使用。

使用 mvnd

优化效果:时间节省一半以上(DSP项目第一次运行时,从4分钟缩减为2分钟,第二次运行只要1分钟10秒)。

安装比较简单,点上面的链接进去,按文档操作即可。

安装后可以简单配置一下:在.m2目录下添加 mvnd.properties 文件,参考配置:

ini 复制代码
mvnd.minHeapSize = 512M
mvnd.maxHeapSize = 3G
mvnd.idleTimeout = 10 hours
mvnd.minThreads = 4
mvnd.threads = 4
mvnd.duplicateDaemonGracePeriod = 1 hours

全面的配置文件参考:github.com/apache/mave...

这里大家可能有个疑问:为什么上面的流水线中不使用mvnd?主要原因是:

  1. mvnd初始化工作需要一些时间,第一次运行的时候节省的时间会少一些;而流水线每次都会新建编译环境,所以mvnd进程没法复用;
  2. 需要在云平台额外构建mvnd的镜像;
  3. 经过其他优化操作后,流水线的任务中,编译已经不再是瓶颈,再进一步优化没有意义(木桶效应)。
相关推荐
Java探秘者7 分钟前
Maven下载、安装与环境配置详解:从零开始搭建高效Java开发环境
java·开发语言·数据库·spring boot·spring cloud·maven·idea
攸攸太上8 分钟前
Spring Gateway学习
java·后端·学习·spring·微服务·gateway
罗曼蒂克在消亡24 分钟前
graphql--快速了解graphql特点
后端·graphql
潘多编程27 分钟前
Spring Boot与GraphQL:现代化API设计
spring boot·后端·graphql
大神薯条老师1 小时前
Python从入门到高手4.3节-掌握跳转控制语句
后端·爬虫·python·深度学习·机器学习·数据分析
2401_857622662 小时前
Spring Boot新闻推荐系统:性能优化策略
java·spring boot·后端
AskHarries2 小时前
如何优雅的处理NPE问题?
java·spring boot·后端
计算机学姐3 小时前
基于SpringBoot+Vue的高校运动会管理系统
java·vue.js·spring boot·后端·mysql·intellij-idea·mybatis
猿java4 小时前
Cookie和Session的区别
java·后端·面试
程序员陆通4 小时前
Spring Boot RESTful API开发教程
spring boot·后端·restful