I just ported one of our big project to Gradle and we just found out (via scans) that compileJava on simple modifications is taking much longer compared to our previous setup (plain project, dependencies included via Netbeans Libraries).
Previously, whenever something was modified only a few classes had to be recompiled (modifying a String triggers just 8 class for recompilation, to say), and the whole takes ~1s.
Honestly I’m reluctant to do this because this means some overhead like restructuring the project into modules (having different sources under different module/src/main/java) and with their corresponding build.gradles and their relative inter-dependencies
I’ll look into 2, for 3 I have no idea what it means, I’ll reserach
how can I check it? --info clearly mention full recompilation
You can see in the link above (here again), it’s a gist (I just modify a System.println in the mentioned class to simulate the smallest change):
Task ‘:compileJava’ is not up-to-date because:
Input property ‘source’ file D:\DEVELOPMENT\EMM-Check\src\main\java\ec\gui\dialogs\vrserver\EC_VrClientListener.java has changed.
Created classpath snapshot for incremental compilation in 0.005 secs. 2061 duplicate classes found in classpath (see all with --debug).
Class dependency analysis for incremental compilation took 0.075 secs.
Full recompilation is required because ‘EC_VrClientListener.java’ was changed. Analysis took 0.083 secs.
Compiling with JDK Java compiler API.
Btw, this prints true, so I guess incremental compilation is on
Are you changing a constant in the class? This is from the user manual:
Since constants can be inlined, any change to a constant will result in Gradle recompiling all source files. For that reason, you should try to minimize the use of constants in your source code and replace them with static methods where possible.
This question comes up all the time. I also have the impression (anecdotal evidence - therefore not worth much) that Gradle is slower then for example Ant.
Maybe the Gradle team could make a poll where people can suggest 3 big and popular open source Java projects. Once 3 projects are selected the Gradle team writes builds for all of them in Gradle and shows through some build time comparison that Gradle is in fact not slower. Also it could show how easy it is to move to Gradle with your build.
Then host those comparisons (including all necessary files to run them) on Github and people can benchmark themselves.
This build performance comparison Github project could serve as a future test to see if build time went down or got faster with future releases of Gradle.
True. And it is slower then IDEA. And IDEA is slower in building the Eclipse. Gradle should take a hard look at what Eclipse is doing and copying it. Eclipse builds a model from source code so it knows about Global Constants and inlining is no problem. Full recompiles are NEVER necessary.
Normally, Gradle will be much faster that Ant and Maven for incremental scenarios, since neither Ant nor Maven support incremental builds nor incremental compilation.
If it is not faster, then something is wrong which should be fixed. The first place to look how to make your builds faster is the performance guide. If that does not help, ask in the forums (here) or open an issue.
I agree that bandwidth is key here. Still there are many possible solutions and some have basically zero bandwidth costs:
Maybe there is an unpublished flag for javac that prevents inlining of public constants and you allow people to turn it on? Maybe reach out to people at Oracle (if the flag does not exist convince them to add it) or dig through the OpenJDK sources to find the flag.
Could the annotation mechanism somehow prevent constant inlining? People could then add those annotations to their constants.
Can’t you just check if .java files containing public constants have changed since the last compile to prevent a full recompile? I know this doesn’t cover all cases of full recompile but it would be a start. Or are you doing this already?
Use spoon or Eclipse JDT to build a source model that knows when constants have changed. This would basically make full recompiles a thing of the past. Arguably this is also the most costly in terms of bandwidth to implement.
P.S.: I still think a single Github project that builds popular projects with Gradle and compare that to their original build mechanism (Maven, ANT, etc.) in terms of performance would be of great benefit to Gradle.
1.: There is no flag for javac.
2: Why don’t you replace the constants by getters? That solves the problem - no more inlining.
3: We already do this: if the changed Java files do not contain any constants, only the required files are recompiled and not everything
4: That is very involved and we would move away from using javac which doesn’t sound like the direction we want to go.
If you have a Github project at hand, then we are more than happy to compare the different build systems and different Gradle versions there. We currently create our own test projects, feel free to check them out. The instructions how to create them are here.