How can I increase maxHeapSize of gradle test - gradle

OutOfMemoryError occurs when I run gradle test.
I want to increase max heap size of my test task.
I know that I can increase max heap size by defining maxHeapSize="1024m"
test {
maxHeapSize="1024m"
}
But I don't want to change the build.gradle file.
Can I increase maxHeapSize in command line interface like ./gradlew test -DmaxHeapSize=1024m

You can add this to gradle.properties
org.gradle.jvmargs=-Xmx1g
or at run-time
./gradlew test -Dorg.gradle.jvmargs=-Xmx1g

Related

Can Gradle fail the build if the jar is too big?

What is a good way for gradle to warn the developer that the code/dependency change they’re making makes the built jar too big?
We’re making updates to a repo that builds a jar that’s deployed in an AWS Lambda function. We are limited to 50MB for the executable. We’d ideally like the devs to get this feedback much before our CI/CD tries to upload to a lambda function and fails.
You could define and use a custom task to implement the file size check, and create a dependency between this task and the task that produces the Jar.
Assuming you are using Sprinboot, you could create a finalizer task that will be executed just after the bootJar task and make the build fail when jar size exceeds a certain limit.
Simple implementation as example:
task jarSizeChecker() {
def maxSize = 15_000_000 // jar size limit in bytes
group "verification"
description "Checks that the produced jar size does not exceed the defined limit"
doLast {
println " checking jar size"
def jarFileSize = bootJar.archiveFile.get().getAsFile().length()
println " fileSize is ${jarFileSize}"
if (jarFileSize > maxSize) {
throw new GradleException("Jar size exceed the defined limit")
}
}
}
bootJar.finalizedBy(jarSizeChecker)
Result:
$ ./gradlew bootJar
[...]
> Task :bootJar
> Task :jarSizeChecker FAILED
checking jar size
fileSize is 17333895
7 actionable tasks: 5 executed, 2 from cache
FAILURE: Build failed with an exception.
* Where:
Build file 'C:\dev\workspaces\...\build.gradle'
* What went wrong:
Execution failed for task ':jarSizeChecker'.
> Jar size exceed the defined limit

Cannot configure Intellij Groovy unit test JVM memory

In short, I tried to use Intellij edit configurations VM to add -Xmx6g, I tried adding to the environment using GROOVY_OPTS, I tried adding to gradle.properties as org.gradle.jvmargs=-Xmx6g
None worked.
Turns out all the above set the JVM for the gradle daemon, but tests run on a different JVM.
To set XMX for your tests, edit the build.gradle file by adding
test {
minHeapSize = "2000m"
maxHeapSize = "6000m"
}

gradle.properties settings not considered

As a starter in gradle I am converting a project from maven to gradle. When running tests I get an OutOfMemoryError: Java heap space. If I add
tasks.withType(Test) {
jvmArgs = ['-Xmx2g']
}
to build.gradle then it works. However, if that is configured only in gradle.properties as org.gradle.jvmargs=-Xmx2g then it doesn't.
Same for the encoding. There is one test which is only running successful if GRADLE_OPTS=-Dfile.encoding=UTF-8 is set. But if I set systemProp.file.encoding=UTF-8 in gradle.properties it doesn't.
Why is that?
The answer is described in the Gradle DSL documentation for the Test task.
Test are always run in (one or more) separate JVMs.
Whatever you configure in gradle.properties environment variable applies to the Gradle JVM process only.
Maximum heap size is configured like you did via jvmArgs or, preferably, via maxHeapSize.
Regarding file encoding & GRADLE_OPTS, I don't have a definite answer. My best guess is that it has just not been implemented this way. You can set the file encoding on a per project basis for compilation tasks like this:
tasks.withType(Compile) {
options.encoding = 'UTF-8'
}
From: Gradle Goodness: Set Java Compiler Encoding

How to pass system properties to the tests in gradle in the smart way?

build.gradle
tasks.withType(Test){
systemProperties=System.properties
println systemProperties['param']
}
Now I can either pass parameters in the command line:
gradle test -Dparam=10
or put them in gradle.properties:
systemProp.param=15
Ideally I would like to put the defaults in the gradle.properties, and be able to overwrite them from the command line. Unfortunately if I do that, the gradle.properties has precedence, and -Dparam=10 is ignored.
Could you offer any solutions on that?
https://issues.gradle.org/browse/GRADLE-2122
It works since 2.12 or 2.13 "the smart way" already!
The example above is working, the command line -D option overdrives the defaults in gradle.properties
I am using gradle 2.12 and sharing how I used it:
test {
// support passing -Dsystem.property=value to bootRun task
systemProperties = System.properties
}
I have JUnit tests that I wanted to skip unless a property was used to include such tests. Using JUnit Assume for including the tests conditionally:
//first line of test
assumeThat(Boolean.parseBoolean(System.getProperty("deep.test.run","false"),true)
Doing this with gradle required that the system property provided at the time of running gradle build, shown here,
gradle build -Ddeep.test.run=true
was indeed passed through to the tests.
Hope this helps others trying out this approach for running tests conditionally.

Why does my large multi-project gradle build start up slowly?

I am on a team that has a large multi-project build (~350 modules) and we have noticed that doing an individual build (-a) still takes a large amount of time. When building the entire set of things the overhead isn't so bad, but when we do something like:
cd my/individual/project
gradle -a --configure-on-demand --daemon build
that it still takes 30-40 seconds just in the configuration phase (before it starts building anything, which we measure using the --dry-run option)
We have approximately 10 custom tasks and we are setting the inputs and outputs for those tasks but we still see this inordinately long configuration time. We are using gradle 1.10
It's hard to say from a distance. A common mistake is to do work in the configuration phase that should be done in the execution phase. Here is an example:
task myTask {
copy {
from ...
to ...
}
}
Here, the project.copy method will be called (and therefore copying will take place) every single time the task is configured, which is for every single build invocation - no matter which tasks are run! To fix this, you'd move the work into a task action:
task myTask {
doLast {
copy {
from ...
into ...
}
}
}
Or even better, use a predefined task type:
task myTask(type: Copy) {
from ...
into ...
}
Some steps you can take to find the cause(s) for performance problems:
Review the build
Run with --info, --debug, or --profile
Profile the build with a Java profiler
PS: Specifying inputs and outputs doesn't shorten configuration time (but likely execution time).

Resources