Gradle 1.9 runs our build slower than 1.8

Our build runs slower on 1.9 than on 1.8.

Our build runs in the following gradle-reported times:

With the daemon, parallel: 1.8

4 mins 23.141 secs 1.9

4 mins 48.627 secs

Without the daemon, parallel (I can explain why some people don’t use the daemon elsewhere): 1.8

4 mins 26.399 secs 1.9

5 mins 7.767 secs

All runs were on Ubuntu 12.04, 4 core i7 2600 with 8 hyperthreads, 16 GB RAM.

A windows machine shows similar results: roughly 40 seconds longer in 1.9.

I couldn’t use bisection to find the commit that slowed things down because in the early RCs for 1.9, our build failed with a fatal error that was fixed in RC3 or RC4.

The only thing I observed that may be related to this is that in 1.8, only one process running org.gradle.process.internal.launcher.GradleWorkerMain was created, while in 1.9, 4 or 5 such processes were created.

If someone could suggest whether it’s possibly with a small patch to modify 1.9 to only create 1 process running org.gradle.process.internal.launcher.GradleWorkerMain, I’d gladly test it.


Do you use ‘tasks.withType(JavaCompile) { options.fork = true }’ or the like?

Re: options.fork: we use it but for Scala not java.

This is an update, where removing the forking in Scala decreases the gap in time on Linux (but possibly not on Windows: I’ll have to verify this).

Based on the data below, I suppose you can consider the remaining slowdown minor and ignorable.

Here’s the fragment of our Scala compilation that was forking. The lines that were forking are commented out with //##, and times follow.

[compileScala.scalaCompileOptions, compileTestScala.scalaCompileOptions]*.with {

// […unrelated lines omitted…]

// Scala compilation can be performed outside the Gradle JVM in a dedicated compiler process,

// which can help to deal with memory issues. External compilation is supported both for the

// Ant-based and the Zinc-based Scala compiler. ‘fork = true’ activates external compilation;

// ‘forkOptions’ allows adjusting the memory settings.

//## forkOptions.jvmArgs += ["-XX:MaxPermSize=512m", “-XX:+CMSClassUnloadingEnabled”]

//## forkOptions.memoryMaximumSize = project.get(“scala.memoryMaximumSize”)

//## fork = true }

I have several different execution configurations (e.g. heapsize etc.) not included, but here are the fastest times (same Linux 4 core 8 HT box), using a warm daemon:

Scala fork commented out:

1.8: 4:23, 3:59, 4:12, 3:57 1.9: 4:18, 4:21, 4:13, 4:24, 4:07

Original times with Scala forking:

1.8: 4:31 1.9: 4:47, 4:43

From this I conclude that Scala forking produces a slowdown in both builds, and without Scala forking the 1.8 build is around 4:07 +/- a few seconds, and the 1.9 build is around 4:18 +/- a few seconds.

If it’s simple to suggest what code patch would move back to one org.gradle.process.internal.launcher.GradleWorkerMain, I would like to test it.

Additional info:

Times with Scala fork disabled, running without daemon (some people run without the daemon for reasons I can explain):

1.8: 4:12, 4:16, 4:17 1.9: 4:54, 4:34, 4:31

I have located the gradle build configuration that causes 4 child processes to be launched. Changing this configuration to disable parallelism causes gradle to only launch one child process of each “org.<…>” type, identically between 1.8 and 1.9, and to complete in 6:28 for both 1.8 and 1.9.

This difference was caused by 1.8 and 1.9 having different behavior for our non-default gradle build configuration.

After commenting out the lines shown below, 1.9 only launches one process of each type. (I’m including the files without their entire reference context, but this should suffice.)

gradle/java.gradle: tasks.withType(Test) {

useTestNG { //

parallel = “tests” //

threadCount = Runtime.runtime.availableProcessors() / 2


} }

gradle/java_base.gradle: tasks.withType(Test) { // maxParallelForks = Runtime.runtime.availableProcessors() / 2

[…omitted…] }

So for reference, the way to locate such issues using grep would be to search all Gradle build files for either “fork” or “parallel” (ignoring case).

At this point, we know why our build behaves as it does, and I doubt it’s worth addressing the fact that this behaves differently in 1.8 and 1.9, although it’s concerning that the change in 1.9 makes this run slower. We have enough information to optimize the parallelism parameters in our build.