Peter Palaga
Peter Palaga
↘ ↙
Lines of Java Code1 | Maven modules2 | mvn clean install |
|
Camel Quarkus | 93K | 1371 | 23.5 min |
Camel | 1609K | 612 | 32.6 min |
Quarkus | 594K | 1161 | 11.1 min |
1) cloc --include-lang=Java .
2) mvn clean && find . -type f -name 'pom.xml' | wc -l
mvnd
a.k.a. Maven Daemon-DskipTests
async-profiler
or any other Java profiler
export MAVEN_OPTS="-agentpath:/path/to/libasyncProfiler.so=start, event=cpu,file=mvn-profile.html"
mvn clean install -DskipTests -Dformatter.skip -Dimpsort.skip ...
# in Camel Quarkus
$ mvn clean install \
-DskipTests \
-Dformatter.skip \
-Dimpsort.skip \
-Denforcer.skip \
-Dcamel-quarkus.update-extension-doc-page.skip \
-Dskip.installyarn \
-Dskip.yarn \
-Dlicense.skip \
-Dquarkus.build.skip
-Dgmaven.execute.skip # underway https://github.com/groovy/gmaven/pull/27
...
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 04:34 min # down from 23:27 min by mvn clean install -DskipTests
public class SomeMojo extends AbstractMojo {
@Parameter(property = "some.skip", defaultValue = "false")
boolean skip;
@Override
public void execute() {
if (skip) {
getLog().info("Skipping as requested by the user");
return;
}
...
}
}
Mojo.execute()
<project>
... <!-- Proper skipping -->
<build>
<plugins>
<!-- Only plugins essential for the fast build -->
<plugin><artifactId>maven-compile-plugin</artifactId></plugin>
<plugin><artifactId>maven-jar-plugin</artifactId></plugin>
<plugin><artifactId>maven-install-plugin</artifactId></plugin>
...
</plugins>
</build>
<profiles>
<profile>
<id>full</id>
<activation>
<property>
<name>!quickly</name><!-- Active by default unless -Dquickly is passed -->
</property>
</activation>
<build>
<plugins>
<!-- All other plugins -->
<plugin><artifactId>maven-enforcer-plugin</artifactId></plugin>
<plugin><artifactId>maven-surefire-plugin</artifactId></plugin>
<plugin><artifactId>maven-failsafe-plugin</artifactId></plugin>
<plugin><artifactId>groovy-maven-plugin</artifactId></plugin>
...
</plugins>
</build>
</profile>
</profiles>
</project>
$ mvn clean install -Dquickly
...
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 04:01 min # down from 04:34 min by
#
# mvn clean install -DskipTests -Dformatter.skip ...
#
Java is fast *
* When warmed up
Measurable through a simple experiment:
package org.apache.maven;
public class DefaultMaven implements Maven {
...
private MavenExecutionResult doExecute( MavenExecutionRequest request ) {
System.out.println("End of Maven init: " + System.currentTimeMillis());
request.setStartTime( new Date() ); // Maven measures from here
}
...
}
$ echo $(($(date +%s%N)/1000000)) && mvn clean install -Dquickly
1634117024986
...
End of Maven init: 1634117025765
$ echo "$((1634117025765-1634117024986))"
779 # Maven start time in milliseconds
mvn clean install -DskipTests -Dformatter.skip -Dimpsort.skip ...
# in Camel Quarkus
- the Maven Daemon
https://github.com/apache/maven-mvnd
mvnd
- how to install
|
⇄ |
Daemon
|
mvnd
demo$ git clone camel quarkus
$ cd camel-quarkus
$ mvnd install -Dquickly
...
# Try CTRL B, + and - keystrokes
# Check mvnd --status and mvnd --help in another terminal
$ mvnd install -Dquickly
...
$ mvnd install -Dquickly
...
mvnd
speed gainsA build with | Many modules (relatively independent) cd camel-quarkus && \
|
Single modulecd camel-quarkus/extensions-core/core/deployment && \ |
||
-DskipTests |
-Dtest=CamelBeansUnremovableTest |
|||
mvn baseline |
4:01 min | 10.11 sec | 12.79 sec | |
mvnd 1st |
1:19 (3x) | 9.15 (1.1x) | 11.82 (1.1x) | |
mvnd 2nd |
1:04 (3.8x) | 2.37 (4.3x) | 5.26 (2.4x) | |
mvnd 3rd |
1:01 (4x) | 1.19 (5.3x) | 4.86 (2.6x) | |
Gains through |
|
|
mvnd
- Parallel builds Runtime.getRuntime().availableProcessors() - 1
-T<n>
or -T<n>C
supported like with stock Mavenbuilder
builder
since Maven 3.2.1singlethreaded
(default)multithreaded
(with -T)mvnd
- Smart builderbuilder
provided by mvnd
A
/ \ Maven module dependencies
B C (Lower depends on upper)
\ /
D
No issues with serial builderC
could be reading a file in B
's target
folderC
's test could dynamically read an artifact produced by B
from the local Maven repositorySimple remedy: -1/--serial
to force the serial builder
<!-- Add this in C -->
org.my-group
B
${project.version}
pom
test
*
*
This won't add any real dependency to C
but it will guarantee that B
is fully built before C
Plugins may do nasty things
-1/--serial
may help
Better: Report/fix the issue in the given plugin
mvnd
drawbacksA build with | Many modules (relatively independent)cd camel-quarkus && mvn[d] clean install -Dquickly
|
||
Machine | Lenovo ThinkPad P1 Gen 3 Core i7 10850H 12 cores 2.7 GHz (baseline) |
|
Self made desktop AMD Ryzen Threadripper 1920X 12 cores, 24 threads 3.5 GHz (1.3x) |
mvn |
4:01 min | 3:42 min (1.1x) | |
mvnd 1st |
1:19 | 0:55 (1.4x) | |
mvnd 2nd |
1:04 | 0:42 (1.5x) | |
mvnd 3rd |
1:01 | 0:40 (1.5x) |
Machine | Lenovo ThinkPad P1 Gen 3 Core i7 10850H 12 cores 2.7 GHz |
|
Self made desktop AMD Ryzen Threadripper 1920X 12 cores, 24 threads 3.5 GHz (1.3x) |
Purchase price | 2630,- € (Oct. 2021) |
~1300 € (Feb. 2020, w/out 🖥️ ⌨️ 🖱️) |
|
Power suply unit | 135 W | 650 W | |
Idle | ~18 W* | ~60 W* | |
Max | 129 W* | 278 W* | |
2h work session (builds, web browsing) |
0.06 kWh* | 0.21 KWh* | |
€/year (0.64 €/kWh**) | 49 € | 171 € |
*) Measured with a budget power meter from a hobby market
**) ENGIE single rate
Techniques to speed up Maven builds