互联网技术团队的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本地编译加速
如果你是一次过的选手,写完代码直接提交的,可以跳过此小节。
如果你需要本地编译,如:
- 需要确保代码能编译成功,避免提交之后影响流水线及其他同学的工作;
- 需要在本地起服务进行调试。
那么编译加速优化后,能节省日常开发大量的时间。
优化效果
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?主要原因是:
- mvnd初始化工作需要一些时间,第一次运行的时候节省的时间会少一些;而流水线每次都会新建编译环境,所以mvnd进程没法复用;
- 需要在云平台额外构建mvnd的镜像;
- 经过其他优化操作后,流水线的任务中,编译已经不再是瓶颈,再进一步优化没有意义(木桶效应)。