Actual Build Time Without Tests
|M11||Java / GWT||15.426 s|
|M24||Java / GWT||47.177 s|
|M31||Java / GWT||0.579 s|
mvn clean install -DskipTests -pl '!m7,!m8,!m18'
The build is now done in 2:48 min.
Skip GWT Modules
The GWT modules are taking 1 minute from the build (15.4 + 47.1), if the changes were not related to these modules, they can be skipped too.
mvn clean install -nsu -DskipTests -pl '!m7,!m8,!m18,!m11,!m24'
mvn -T 1C clean install -nsu -DskipTests -pl '!m7,!m8,!m18,!m11,!m24'
Which means Maven uses 1 thread per core for the build. The multiple-thread build is available since Maven 3. When running the project, you can see the message in the console (right after the Reactor Build Order):
[INFO] Reactor Build Order: [INFO] [INFO] ... [INFO] [INFO] Using the MultiThreadedBuilder implementation with a thread count of 8
Maven uses 8 threads because my machine has 8 logical CPU. Actually, the CPU is an Intel Core i7 2.9 GHz, which has Hyper-Theading Technology and makes one physical core appears as two processors to the operating system. So there’re 4 physical CPUs and appears as 8 logical CPUs.
$ sysctl hw.physicalcpu hw.logicalcpu hw.physicalcpu: 4 hw.logicalcpu: 8
Here’s the result of execution:
|Total||1:01 min (Wall Clock)|
As you can see, the time for building each module is longer, but the Wall-Clock time is shorter now: -39%. This option is very useful when you only want to ensure your code compiles.
What is “Wall-Clock” time in Maven? Here’s an answer from Stack Overflow:
By default (without
-T), Maven builds all modules sequentially rather than in parallel. So you only have one process, which (in your example) takes 40s.
You start the build with 4 threads, so the total time of 40s gets divided by 4 threads, so each thread runs for 10s.
The total CPU time stays the same (40s), but the time that passed for YOU is only 10s + some overhead for parallelization. It’s the time that you see when you look on your clock on the wall, therefore it’s called Wall-Clock time.
Only Build The New Changes
If you want the build to be even faster, you shoud build just the project
specified in option
-pl and all the dependent ones (flag
-amd). For example, if I change
a class called
Foo.java, and rebuild the Maven as mentioned before, the
command is (without parallel):
mvn clean install -DskipTests -nsu -pl 'm7' -amd
which takes 02:44 min to complete.
Now, run the same command again in parallel:
mvn clean install -DskipTests -nsu -pl 'm7' -amd -T 1C
which takes 01:55 min to complete.
The build is still not very optimal because of the Ant tasks which take too long to complete. If you don’t need to build the packages in localhost, skip them. This will make the build much faster. So here we will only compile the source code without packaging, and let CI to run the tests and package the software:
mvn clean -nsu compiler:compile compiler:testCompiler
which takes 35.123 seconds to complete.
Now, try again with parallel build:
mvn clean -nsu compiler:compile compiler:testCompiler -T 1C
which takes 18.499 seconds to complete.
What about building only the changes?
mvn clean -nsu compiler:compile compiler:testCompiler -T 1C -amd -pl 'm7'
still taking 18.404 seconds to complete. So I think we reach our limit now :)
I make the summary as Bash alias, so that they can be executed easily in your terminal:
There’re several ways to speed up a Maven project.
- Only build the necessary part of the project
- Use parallel execution if possible
- Execute the right goals, e.g. compilation, rather than all goals
- Build only the changes
- Split into multiple projects :)
Hope you enjoy this article, see you the next time!