speeding up maven execution

posted by qmx on 10 August 2011

I think that every maven related post deserves a small remark.

Why people hate maven so much?

1. Maven downloads the internet

Maven is by essence modular. This means that the package that you just downloaded from Maven site is just a bootstrapper. From a conceptual point of view this is a good thing indeed. The problem is that technically perfect sometimes means boring too.

The boring part comes as a courtesy when you run your first mvn compile. Maven will dilligently try to find the needed dependencies to run the goal compile.

2. Maven needs a good UX shoplift

Hey, Maven is a CLI app!

But who told you that CLI apps should be ugly or unfriendly to use?

When a user runs a simple comand like mvn clean, they probably will get pissed of if they see a lot of http://.... nonsense.

I think that giving users less feedback certainly would make them less pissed of - first calculating what needs to be done, and then showing an unified download progress indicator.

Less is more :)

3. Maven has a XML-centric model

The heart of maven power (and headaches) is the Project Object Model . Every aspect of a Maven project takes this hierarchy into account, and tries to resolve all the project dependencies and lifecycle at once. This is great to ensure consistency, but the POM will be always re-evaluated between Maven runs. This results in lots of time parsing XML files / building the POM, resolving dependencies, rinse and repeat.

Let’s get the facts - Maven has its problems, but it can’t be that bad, can’t it?

So, Maven really sucks? Do you have any contender?

We have several tools trying to take Maven’s empire down (all of them using the Maven dependency repositories)

1. buildr - ruby centric

define 'killer-app' do
  project.version = '0.1.0'
  package :jar

2. sbt - scala centric

// set the name of the project
name := "My Project"

version := "1.0"

organization := "org.myproject"

// add a test dependency on ScalaCheck
libraryDependencies += "org.scala-tools.testing" %% "scalacheck" % "1.8" % "test"

3. lein - clojure centric

(defproject myproject "0.5.0-SNAPSHOT"
  :description "A project for doing things."
    :url "http://github.com/technomancy/myproject"
      :dependencies [[org.clojure/clojure "1.2.1"]
                       [org.clojure/clojure-contrib "1.2.0"]]
                         :dev-dependencies [[lein-ring "0.4.5"]])

4. gradle - groovy centric

task hello {
  doLast {
    println 'Hello world!'

5. ant - the traditional build tool + ivy - dependency management

    <project name="MyProject" default="dist" basedir=".">
        simple example build file
        <!-- set global properties for this build -->
        <property name="src" location="src"/>
        <property name="build" location="build"/>
        <property name="dist"  location="dist"/>

The point is, all these tools have their strong points (mostly syntactic sugar, and this is a good thing™), but no one has the same adoption Maven has.

Being somewhat related to Maven ecossystem, they suffer too:

So, what can we do to to improve actual scenario?

Making Maven suck less

The Sonatype guys did an awesome job tracking down these shortcomings, and discovered that they could reduce Maven’s overhead by pre-loading the POM hierarchy by using a Maven Shell, so it caches a lot of costly operations.

In my local tests, it shove down about 26% of build/test cycle time \o/

  • 1st run, normal Maven : 4m22s
  • 1st run, mvnsh : 3m42s (26%)
  • 2nd run, mvnsh : 3m36s

The installation is straightforward - just unpack and put the <mvnsh-folder>/bin on your $PATH, then run mvnsh inside any folder containing a pom.xml file. After that, just issue normal mvn commands as you normally would do.

For me, Maven is an evil need. Lots of plugins, mostly sane conventions, fast environment setup (given a generous internet link). What do you think?