优化maven构建性能



我有一个Maven web应用程序。这花了太多的时间(30-40分钟)。我想把它减少到10分钟以内。我的pom.xml如下。

<?xml version="1.0" encoding="utf-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>se.mysite.etc.settings</groupId>
        <artifactId>projects</artifactId>
        <version>1.5</version>
    </parent>
    <groupId>se.myweb.portal</groupId>
    <artifactId>myweb-se-main</artifactId>
    <name>myweb-se-main</name>
    <version>3.1.81-B2_forv-SNAPSHOT</version>
    <packaging>pom</packaging>
    <inceptionYear>2009</inceptionYear>
    <properties>
        <release.version>${project.version}</release.version>
        <acc.version>2.3.42-TEST-MAINT-SNAPSHOT</acc.version>
        <cxf.version>2.5.3</cxf.version>
        <spring.version>3.0.3.RELEASE</spring.version>
        <spring.security.version>2.0.4</spring.security.version>
        <spring.webflow.version>2.1.1.RELEASE</spring.webflow.version>
        <commonportal.version>1.9.9-SPRING3</commonportal.version>          
        <junit.version>4.5</junit.version>
        <java.source.version>1.6</java.source.version>
        <cobertura.maxmem>1024M</cobertura.maxmem>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <scm>
        <connection>scm:hg:http://test1/myweb</connection>
        <developerConnection>scm:hg:http://test1/myweb</developerConnection>
        <tag/>
        <url>http://test1/myweb</url>
    </scm>
    <profiles>
        <profile>
            <id>dev</id>
            <dependencies>
                <!--some dependencies-->
            </dependencies>
            <modules>
                <module>../project1</module>
                <module>../project2</module>
                <module>../project3</module>
                <module>../project4</module>
            </modules>
        </profile>
        <profile>
            <id>dist</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <dependencies>
                <!--some dependencies-->
            </dependencies>
            <modules>
                <module>../project1</module>
                <module>../project2</module>
                <module>../project3</module>
                <module>../project4</module>
                <module>../project5</module>
                <module>../project6</module>
            </modules>
        </profile>
        <profile>
            <id>backend</id>
            <dependencies>
                <!--some dependencies-->
            <modules>
                <module>../project3</module>
                <module>../project1</module>
                <module>../project2</module>
                <module>../project4</module>
                <module>../project9</module>
            </modules>
        </profile>
        <profile>
            <id>frontend</id>
            <!--some dependencies-->
            <modules>
                <module>../project10</module>
                <module>../project11</module>
            </modules>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-surefire-plugin</artifactId>
                        <version>2.12.4</version>
                        <configuration>
                            <forkMode>always</forkMode>
                            <argLine>-Xms512m -Xmx2048m -XX:MaxPermSize=2048m</argLine>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>
        <profile>
            <id>webtest</id>
            <build>
                <finalName>myweb-web-test</finalName>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-surefire-plugin</artifactId>
                        <configuration>
                            <argLine>-XX:MaxPermSize=512m</argLine>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
            <!--some dependencies-->
            <modules>
                <module>../myweb-web-test</module>
            </modules>
        </profile>
        <profile>
            <id>redeploy_web_app</id>
            <activation>
                <property>
                    <name>redeployWebApp</name>
                </property>
            </activation>
            <properties>
                <user.tomcat.home>${env.DEST_DIR}</user.tomcat.home>
            </properties>
            <build>
                <pluginManagement>
                    <plugins>
                        <plugin>
                            <groupId>org.apache.maven.plugins</groupId>
                            <artifactId>maven-antrun-plugin</artifactId>
                            <version>1.6</version>
                            <dependencies>
                                <!--some dependencies-->
                            </dependencies>
                            <executions>
                                <execution>
                                    <id>delete_project_artifact</id>
                                    <phase>prepare-package</phase>
                                    <configuration>
                                        <tasks>
                                            <taskdef classpathref="maven.plugin.classpath" resource="net/sf/antcontrib/antcontrib.properties"/>
                                            <if>
                                                <equals arg1="${project.packaging}" arg2="war"/>
                                                <then>
                                                    <echo message="Removing ${project.artifactId}.${project.packaging} from ${user.tomcat.home}/webapps"/>
                                                    <delete dir="${user.tomcat.home}/webapps/${project.artifactId}"/>
                                                    <delete file="${user.tomcat.home}/webapps/${project.artifactId}.${project.packaging}"/>
                                                </then>
                                            </if>
                                        </tasks>
                                    </configuration>
                                    <goals>
                                        <goal>run</goal>
                                    </goals>
                                </execution>
                                <execution>
                                    <id>copy_project_artifact</id>
                                    <phase>package</phase>
                                    <configuration>
                                        <tasks>
                                            <taskdef classpathref="maven.plugin.classpath" resource="net/sf/antcontrib/antcontrib.properties"/>
                                            <if>
                                                <equals arg1="${project.packaging}" arg2="war"/>
                                                <then>
                                                    <echo message="Copying ${project.build.finalName}.${project.packaging}"/>
                                                    <copy file="${project.build.directory}/${project.build.finalName}.${project.packaging}" overwrite="true" tofile="${user.tomcat.home}/webapps/${project.artifactId}.${project.packaging}"/>
                                                </then>
                                            </if>
                                        </tasks>
                                    </configuration>
                                    <goals>
                                        <goal>run</goal>
                                    </goals>
                                </execution>
                            </executions>
                        </plugin>
                    </plugins>
                </pluginManagement>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-antrun-plugin</artifactId>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>
    <!-- General dependencies -->

    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>cobertura-maven-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <instrumentation>
                        <excludes>
                            <exclude>se.mysite/**/Test*.class</exclude>
                        </excludes>
                    </instrumentation>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>clean</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <!-- TODO: Use UTF-8 here or not??? -->
                    <encoding>UTF-8</encoding>
                    <!-- encoding>ISO-8859-1</encoding-->
                    <source>${java.source.version}</source>
                    <target>${java.source.version}</target>
                    <showDeprecation>true</showDeprecation>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-release-plugin</artifactId>
                <version>2.1</version>
                <configuration>
                    <scmCommentPrefix>II    Release:</scmCommentPrefix>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <organization>
        <name>mysite AB</name>
        <url>http://www.mysite.se</url>
    </organization>
</project>

下面是我的编译命令。

mvn -U -DartifactsTarget=$DEST_DIR/lib/tpp -P dev -Dmaven.test.failure.ignore=true -Dtesting.testsToExclude=**/Test*.java -f pom.xml $* -DredeployWebApp install

建造大约需要30分钟。

我使用的是maven 3.0.4。我探索了使用以下选项可以优化构建时间。

  1. 使用maven并行处理
  2. 使用丛编译器插件
  3. 使用maven电源壳

如果我需要对pom.xml或任何其他可以优化性能的技术进行任何其他更改,请告诉我。

优化Java项目的Maven构建归结为三个因素:

  1. 编译和测试
  2. Maven构建的复杂性
  3. 优化Maven(二进制)性能

编译和测试

例如,如果您的应用程序中有GWT,并且您正在为20种不同的排列进行编译,那么如果您一直在这样做,这将是一个问题。

有一些方法可以绕过这个问题,可能只在需要时进行完整的构建,或者通过使用draftCompileoptimizationLevel选项来限制构建。

同样的事情也适用于你的测试:如果你有数百个测试,每个测试所花费的时间长度开始变得重要。提高测试性能的常用方法有:

  1. 不要使用Thread.sleep(..),使用互斥锁和锁
  2. 在多个测试之间共享配置(持久性单元、mock),而不是在每个测试中进行设置
  3. 除非你真的需要,否则把它变成一个单元测试,而不是集成测试。无论如何,太多的集成测试都是一种糟糕的代码气味

Maven构建的复杂性

如果你有10个或数百个模块,有一个复杂的依赖树,maven将需要时间来计算依赖树。使用"dependency:analyze"来确定是否存在未使用的依赖项并将其删除。

此外,每个模块的构建中使用的插件数量会增加构建时间。

优化Maven(二进制)性能

我使用以下选项:

export MAVEN_OPTS="-Dmaven.wagon.provider.http=httpclient -Dmaven.artifact.threads=12 -Dhttp.tcp.nodelay=false -Xmx2048M -Xss256M -XX:+CMSClassUnloadingEnabled -XX:-UseGCOverheadLimit -XX:MaxPermSize=256M -T2C"

  • -Dmaven.wagon.provider.http=httpclient:更改http连接机制,我的理论是Apache HttpClient库比默认的Java HttpURLConnection类更快更好
  • -Dmaven.artifact.threads=12:用于下载工件的线程数
  • -Dhttp.tcp.nodelay=false:关闭Nagle的算法以提高性能(但也增加了使用的带宽)。这是Wagon的一处房产
  • -T2C:这是在maven 3中引入的一个expiremental构建:每个构建的线程数。请参阅Maven 3中的并行构建

如果你有其他建议,请编辑这篇文章!

最新更新