Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

optimizing maven build performance

I have a Maven web application. This is taking too much time to build(30-40 mins).I would like to reduce it to less than 10 mins. My pom.xml is as below.

<?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>

My compile command is below.

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

It is taking almost 30 mins to build.

I am using maven 3.0.4. I explored that using the following options we can optimize the build time.

  1. Using maven parallel processing
  2. Using plexus compiler plugin
  3. Using maven power shell

Please let me know if I need to any other changes to my pom.xml or any other techniques that would optimize the performance.

like image 470
Patan Avatar asked Mar 21 '26 19:03

Patan


1 Answers

Optimizing the Maven build of a Java project comes down to 3 factors:

  1. Compilation and Tests
  2. Complexity of the Maven build
  3. Optimizing the Maven (binary) performance

Compilation and Tests

If, for example, you have GWT in your application and you're compiling for 20 different permutations then this will be a problem if you're doing this the whole time.

There are ways to get around this by maybe only doing the full build when you need to, and otherwise limiting the build by using the draftCompile or optimizationLevel options.

The same thing applies to your tests: if you have hundreds of tests, the length of time that each test takes starts to become significant. Common ways to increase performance in tests are:

  1. Don't use Thread.sleep(..), use mutex's and locks.
  2. Share configuration (persistence units, mocks) across multiple tests instead of doing the setup per test.
  3. Make it a unit test instead of an integration test, unless you really need to. Too many integration tests is a bad code smell, in any case.

Complexity of the Maven Build

If you have 10's or hundreds of modules, with a complex dependency tree, maven will need time to calculate the dependency tree. Use `dependency:analyze' to figure out whether or not there are unused dependencies and remove them.

Also, the number of plugins used in each module's build will increase the build time.

Optimizing Maven (binary) performance

I use the following options:

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: Changes the http connection mechanism, my theory is that the Apache HttpClient library is faster and better than the default Java HttpURLConnection class
  • -Dmaven.artifact.threads=12: The number of threads used to download artifacts.
  • -Dhttp.tcp.nodelay=false: Turns off Nagle's algorithm increasing performance (but also bandwidth used). This is a Wagon property.
  • -T2C: This was an expiremental build introduced in maven 3: the number of threads per build. See Parallel builds in Maven 3

Please feel to edit this post if you have other tips!

like image 133
Marco Avatar answered Mar 23 '26 09:03

Marco