Very slow builds

Before gradle my project setup used to be: 1 main project (Core)
with the main source code and 4 other projects (lets call them Project A – D) that
were rarely modified. In order to build everything I had to run batch scripts
that would jar my Projects A – D into separate jars that I would later
copy/paste into the servlet/web-inf/lib of the apache folder. The Core project
was configured in Eclipse to be built automatically to
apache_path/servlet/web-inf/classes.

I did not like the fact that I had to jar everything
manually and also that I had to download every dependency like apache commons
also manually which became later hard to maintain now that I have more than 50
jars that are out of date. One good thing I really liked was that any change I
made in the core project would get automatically picked up by Tomcat (instant
compile). If the change was major I would just have to restart Tomcat and run
my program (3.5 seconds.)

I got tired of this dependency hell and I decided to use
gradle. At first I played around with single project build but later I noticed
that multi project build would be better.

Now I have (ParentProject) that has (Child, ProjectA,
ProjectB, ProjectC, ProjectD).

ParentProject has: build.gradle, gradle.properties,
settings.gradle, wrapper (2.5).

Parent: build.gradle
http://pastebin.com/aarD1w1L

Parent: Settings.gradle

Include “Core”, “ProjectA”, “ProjectB”, “ProjectC”, “ProjectD”

Parent: gradle.properties

org.gradle.daemon=true
org.gradle.parallel=true

Core Project: build.gradle
http://pastebin.com/sh2nn963

ProjectA-D: build.gradle
http://pastebin.com/1CqJy0JS

Now here is the problem. Now when I run “gradle assemble” it
takes about 25 seconds on my (i7 4770, 16 GB of Ram) while on other developer’s
machine it takes 1-2 minutes in average. I would not care if I have to run this
procedure only once but when I just add “System.out.println(“Hello world”);” my
whole project structure gets rebuild. Eclipse’s instant compile with occasional
tomcat restarts for the single class vs gradle’s 2 minutes build. Feels like a
downgrade to me. Am I doing something completely wrong because one line of “Hello
World” should not force me to rebuild the entire project structure. I tried using parallel and daemon flags but it reduces the build time just by a few seconds.

I mentioned this on IRC, but I’ll say it again. You should run both your build and the build on the other developer’s workstation with “–profile” to get a better understanding of how the build is spending its time. You should also do this when you add that print statement. You haven’t said anything about WHERE you’re adding that print statement, and that might be useful.

I’d also like to understand what you’re doing with tests. On IRC you said those timing estimates didn’t include tests, but you haven’t mentioned that here.

There’s certainly some oddities in these build scripts, but I noticed that project A is writing to the “com” folder of your classes tree, which makes the resulting classes not match the package structure.

Hey @kotorez

All of your projects are writing into the same output directory. This prevents parallelization and will cause all of the compile tasks to be out of date because the contents of their output directories have changed.

What I would do is have all of the projects use their default output location (don’t change it) and add a “deploy” task that will copy what’s needed into the Tomcat directory. You could then either use gradlew deploy each time you want to update Tomcat or run in continuous build gradlew -t deploy, which will update the Tomcat directory each time something changes.

The difference between your and the other developer’s machines might be because of the contents of the output directory (they have a lot more “stuff” in there?), hard drive speeds or environment differences (e.g., they run Gradle with custom JVM arguments).

Thanks. Your suggestion helped.

I decided to make the project build into the default build location. It did stop rebuilding sub projects and it did reduce build time. The bottleneck is my Core project.

I converted the “Core” project to single project model (632 classes) http://pastebin.com/RJx88H3G
When I run “gradlew assemble” this is what I get:

I only added an extra line break in my code, I dont want to wait 28 seconds just to see the changes I made. Is there any way to make it compile only one class or am I expecting too much? Sorry if I am not understanding something, gradle is my first build system.

Thanks.

You could try enabling the incremental Java compiler:

tasks.withType(JavaCompile) {
     options.incremental = true
}

The jar task seems a little weird (taking too long). Do you have lots of files in your resources directory?

edit: ah, just noticed you posted an updated build script… let me look again.

This isn’t going to be incremental because you’re going to always perform a copy.

processResources.doLast( {
copy {
        from( sourceSets.main.java.srcDirs ) {
                include '**/*.properties'
                include '**/*.xml'
                include '**/*.htm'
        }
        into sourceSets.main.output.classesDir
}
})

The right way to do this is to add the paths that need to be copied to the resources sourceSet, although you may run into https://issues.gradle.org/browse/GRADLE-3335 (will be fixed in 2.7).

It looks like you have jars in src/main/resources too? That might explain why the jar task is taking awhile (it has to put the jars inside the final jar).

Is this the build script for the profile screenshot you posted?

Thanks. I noticed one problem when I do incremental build.

When I change srcDirs to ‘src’ instead of default src/main/java my incremental compiles only one class (2.4s) but when I leave default location my incremental compiles every class in the project (20s). If I leave it at src, my project will work but if I decide to re import the project to eclipse I will get import error for duplicating src folders.

main {
java {
srcDirs = [‘src’]
//srcDirs = [‘src/main/java’]
exclude ‘temp/**’
}

That might be just a quirk of how we merge existing Eclipse metadata files. We try not to remove anything if there are existing .classpath or .project files, so we’re probably adding duplicate source directories. I’d try gradle cleanEclipse eclipse to see if that helps (or deleting the files manually).

My eclipse plugin runs those commands but the main source of confusion is why incremental works on src/ and not on src/main/java.
Is not src/main/java default one?

My project structure is:
src/main/java - packages and resources. Hibernate files are mixed with .java.
src/test/java - test src packages and test resources.

I now only have 1 Parent - 1 Child project now. What are the common things I should look after if I want incremental to work properly?

Sorry to bother you again. Here is my debug log. I dont know if it tells you anything. It happens every time I run from src/main/java. All of my compile classes just get deleted.

When you changed the src dir to “src” did you MOVE the source files, or is it thinking that you have classes in package “main.java.com…”?

You said “my eclipse plugin runs those commands”, referring to the “cleanEclipse eclipse” tasks Sterling asked you to run? What happened when you did that? Did you examine your Eclipse project before or after to see if there were duplicate source directories, as Sterling was proposing?