45

I am currently switching from ant to gradle for my multi module web application and at the moment it seems that the current version of Gradle (M9) might be running up against its limits. But maybe (hopefully) it is just a problem of me not understanding the concepts of Gradle good enough or not knowing the "magic performance boost switch". I'd be happy for any hint on how the build performance could be optimized.

The problems: several minutes pass before the first compileJava is displayed, and even if nothing has changed in the sources, the process is running at least 7 minutes until it crashes halfway through :testClasses (at varying subprojects) with the following message:

* What went wrong:
Could not resolve all dependencies for configuration ':mysubproject_X:testRuntime'.
> Java heap space

The project consists of about 30 (partly interdependent) subprojects, the build.gradle of them being more or less the same and are used to build a jar file from each subproject, e.g.

sourceSets {

    main {
        java {
            srcDirs 'src'
        }
    }
}

dependencies {

    compile project(':mysubproject_A')
    compile project(':mysubproject_B')
    compile project(':mysubproject_E')

    compile group: 'commons-lang', name: 'commons-lang', version: '2.2'

}

// copy all non-java files from src
copy {
    from sourceSets.main.java.srcDirs
    into "$buildDir/classes/main"
    exclude '**/*.java'
}

jar {
}

I tried to resolve the heap space problem by ramping up max memory size to 1024M, but it did not help. My main build.gradle file looks like this:

            sourceCompatibility = 1.6
            version = 0.5

            useFindBugs = false

            apply plugin: 'java'

            configurations {
            }

            repositories {
                mavenCentral()
                mavenRepo url:"http://repository.jboss.org/maven2", artifactUrls: ["https://repository.jboss.org/nexus/content/repositories/public","http://opensource.55minutes.com/maven-releases"]
            }


            dependencies {
            }

            buildscript {
                repositories {
                    mavenRepo url: 'http://gradle.artifactoryonline.com/gradle/plugins'
                    flatDir(dirs: "$projectDir/lib")
                }

                dependencies {
                    classpath "org.gradle.plugins:gradle-idea-plugin:0.3.1"
                }
            }

            subprojects {
                apply plugin: 'java'
                apply plugin: 'idea'

                repositories {
                    mavenCentral()
                    mavenRepo url:"http://repository.jboss.org/maven2", artifactUrls: ["https://repository.jboss.org/nexus/content/repositories/public","http://opensource.55minutes.com/maven-releases"]
                }

                dependencies {
                    testCompile 'junit:junit:4.8.2'
                }

                compileJava {
                    options.encoding = 'UTF-8'
                    options.fork (memoryMaximumSize: '1024m') 
                }

                javadoc {
                    options.encoding = 'UTF-8'
                }

                test {
                    testReportDir = file(rootProject.testReportDir)
                    forkEvery = 1
                    jvmArgs = ['-ea', '-Xmx1024m']
                }
            }


            dependsOnChildren()

            task wrapper(type: Wrapper) {
                gradleVersion = '1.0-milestone-9'
            }
trincot
  • 317,000
  • 35
  • 244
  • 286
peterp
  • 3,101
  • 3
  • 22
  • 37
  • 1
    Do you happen to be replacing tokens? I've found this to be the one thing that caused multi-project Gradle build to be an order of magnitude slower because we were doing token replacement over the .gradle cache. – Eric Wendelin Mar 21 '12 at 17:13
  • Thanks for your suggestion. However, there were no replacements involved. Peter Niederwieser's answer below did the trick :) – peterp Mar 22 '12 at 08:45

9 Answers9

66

You need to give more memory to the Gradle JVM, not to the compile task/JVM. One way to do so is via the GRADLE_OPTS environment variable (GRADLE_OPTS=-Xmx512m).

Peter Niederwieser
  • 121,412
  • 21
  • 324
  • 259
  • 6
    Thanks, setting GRADLE_OPTS to -Xmx512m as suggested not only eliminated the Heap Space error, but also speeded the process up enormously. It still takes quite some time to do the build and at some points I am not really sure what Gradle is doing in the background, but I can go on using the profiler from here :) – peterp Mar 22 '12 at 08:44
  • When set it to 512, I get same error again; But when I set it to for example 2048, I get "Could not reserve enough space for 2097152" – Dr.jacky Jan 19 '17 at 07:58
29

If using the Gradle Wrapper you can set DEFAULT_JVM_OPTS in gradlew like this:

DEFAULT_JVM_OPTS="-Xmx512m"

Set it in a similar fashion in gradlew.bat if you're on Windows:

set DEFAULT_JVM_OPTS=-Xmx512m

The Gradle Wrapper task can also be modified to include this automatically. This is how the Gradle developers have solved it:

wrapper {
    gradleVersion = '1.8'

    def jvmOpts = "-Xmx512m"
    inputs.property("jvmOpts", jvmOpts)
    doLast {
        def optsEnvVar = "DEFAULT_JVM_OPTS"
        scriptFile.write scriptFile.text.replace("$optsEnvVar=\"\"", "$optsEnvVar=\"$jvmOpts\"")
        batchScript.write batchScript.text.replace("set $optsEnvVar=", "set $optsEnvVar=$jvmOpts")
    }
}
David Pärsson
  • 6,038
  • 2
  • 37
  • 52
9

I am using following version of gradle.properties to make Gradle performance better in Android projects

# The Gradle daemon aims to improve the startup and execution time of Gradle.
# When set to true the Gradle daemon is to run the build.
org.gradle.daemon=true

# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx10248m -XX:MaxPermSize=256m
org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8

# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
org.gradle.parallel=true

# Enables new incubating mode that makes Gradle selective when configuring projects.
# Only relevant projects are configured which results in faster builds for large multi-projects.
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:configuration_on_demand
org.gradle.configureondemand=true
silwar
  • 6,470
  • 3
  • 46
  • 66
  • 1
    This works great, although I have to disable parallel in my project and I think it's because a custom gradle plugin is mutating existing JARs instead of producing new outputs and leaving the originals alone. Food for thought if parallel isn't working as expected for others. – Coder Guy Mar 15 '21 at 22:22
7

I just found a very nice way to handle this problem. No need for custom gradle wrapper or GRADLE_OPTIONS.

compileJava {
    options.fork = true  // Fork your compilation into a child process
    options.forkOptions.setMemoryMaximumSize("4g") // Set maximum memory to 4g
}

Run Gradle with the --info option to see where it's going to use your parameter for max memory size.

gradle build --info
Dusan Jovanovic
  • 411
  • 4
  • 6
  • 1
    In your `build.grade`. The syntax has changed a bit since then. Here are the [JavaCompile docs](https://docs.gradle.org/current/dsl/org.gradle.api.tasks.compile.JavaCompile.html). – Dusan Jovanovic Apr 13 '18 at 20:32
4

In the gradle.properties file add the following line :

org.gradle.daemon=true

This will boost the build - taken from

https://www.timroes.de/2013/09/12/speed-up-gradle/

shimi_tap
  • 7,822
  • 5
  • 23
  • 23
4

Put the following content to ~/.gradle as gradle.properties

# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Settings specified in this file will override any Gradle settings
# configured through the IDE.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# The Gradle daemon aims to improve the startup and execution time of Gradle.
# When set to true the Gradle daemon is to run the build.
# TODO: disable daemon on CI, since builds should be clean and reliable on servers
org.gradle.daemon=true
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx10248m -XX:MaxPermSize=256m
org.gradle.jvmargs=-Xmx6g -Xms4g -XX:MaxPermSize=8g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
org.gradle.parallel=true
# Enables new incubating mode that makes Gradle selective when configuring projects.
# Only relevant projects are configured which results in faster builds for large multi-projects.
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:configuration_on_demand
org.gradle.configureondemand=true
wukong
  • 2,430
  • 2
  • 26
  • 33
  • 1
    Turning on the gradle daemon works well for speeding up gradle, in general. Every time you invoke gradle, it has to load and parse the build file, then it can start executing. The daemon will load / parse and cache the parsed data. Next invocation, if the build file hasn't changed, it goes MUCH faster. It fails, though, if you ever do "gradle --debug " because you're trying to see the classpath is, what values the variables have, etc. You must turn off the daemon in the config, kill -9 the process THEN do the --debug THEN, after completing the debug, turn it back on in the config. – Meower68 Jun 02 '17 at 16:58
3

I personally went through all the articles here but doing these steps fixed it.

If you are using 32 bit jvm that may be the issue install a 64 bit jvm.

  1. Go to the control panel (search java in windows 10)
  2. find the java application
  3. Double click on java and then view.
  4. In run time parameters add:

    -Xmx 2048m
    
Martin Evans
  • 45,791
  • 17
  • 81
  • 97
Ashwin Bn
  • 41
  • 1
  • 3
  • 1
    For anyone looking for "run-time parameters", in W7 this is under the "Java" tab once you do step 3, then click "View". From there, "run time parameters" will be seen as one of the cells in the grid. – www-0av-Com Aug 14 '17 at 20:34
  • Thank you! I had 32bit and 64bit Java installed and gradle used 32bit instead of 64bit. – blk0ut Nov 30 '17 at 09:09
1

None of the above answers worked for me, then I found this-

My System Configuration-

Windows x64 - JDK 32 bit - Cordova 5.4.1 - Ionic 1.7.12

JVM options for running Gradle can be set via environment variables. You can use either GRADLE_OPTS or JAVA_OPTS, or both. JAVA_OPTS is by convention an environment variable shared by many Java applications. A typical use case would be to set the HTTP proxy in JAVA_OPTS and the memory options in GRADLE_OPTS. Those variables can also be set at the beginning of the gradle or gradlew script.

I added the below mentioned two Environment Variables and solved this issue-

Variable Name: GRADLE_OPTS
Variable Value: -Xmx512m

Variable Name: JAVA_OPTS
Variable Value: -Xmx512m

Hope this helps to guys like me.

Manik Arora
  • 4,702
  • 1
  • 25
  • 48
0

GRADLE_OPTS value in gradlew was set like this for me before

DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"

This was causing compileJava fail like below in Jenkin

What went wrong: Execution failed for task ':compileJava'. GC overhead limit exceeded

Later I had changed DEFAULT_JVM_OPTS like below to make Jekin build success -

DEFAULT_JVM_OPTS="-Xmx512m" "-Xms64m"