// Copyright (C) 2025 Gradle, Inc.
//
// Licensed under the Creative Commons Attribution-Noncommercial-ShareAlike 4.0 International License.;
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

[[best_practices_for_performance]]
= Best Practices for Performance

[[prefer_bin_distribution]]
== Prefer the `-bin` Gradle Distribution

Gradle publishes two distribution variants for each release: `-bin` (binaries only) and `-all` (binaries, sources, and documentation).
For most builds, you should prefer the smaller `-bin` distribution.

Using `-bin` reduces download size and verification effort, speeds up CI and developer builds, and limits the number of artifacts you need to trust.

=== Explanation

Each Gradle release provides:

- `gradle-<version>-bin.zip` – binaries only
- `gradle-<version>-all.zip` – binaries plus sources and offline documentation

In modern setups:

- IDEs and build tools can download sources and documentation directly from repositories or online docs (even when using `-bin` releases).
- The `-all` distribution is rarely required outside of specific offline or air-gapped environments.

Preferring `-bin` helps because:

- It **reduces download and cache size** for CI and local builds.
- There is **less to verify and fewer artifacts to trust** (one smaller archive instead of a larger “everything included” zip).
- It **shortens the feedback loop** when upgrading Gradle.

In special cases (for example, fully offline environments), you can still use `-all`, but it should be a conscious exception rather than the default.

==== Don't Do This

Make sure your Wrapper doesn't point to the `-all` distribution:

`gradle/wrapper/gradle-wrapper.properties`:

[source,properties]
----
distributionUrl=https\://services.gradle.org/distributions/gradle-<version>-all.zip
----

==== Do This Instead

Configure the Wrapper to use the `-bin` distribution:

`gradle/wrapper/gradle-wrapper.properties`:

[source,properties]
----
distributionUrl=https\://services.gradle.org/distributions/gradle-<version>-bin.zip
----

=== References

- <</gradle_wrapper.adoc#configuring_checksum_verification,Gradle Wrapper checksum verification>>

=== Tags

<<tags_reference.adoc#tag:upgrades,`#upgrades`>>, <<tags_reference.adoc#tag:wrapper,`#wrapper`>>

[[use_utf8_encoding]]
== Use UTF-8 File Encoding

Set `UTF-8` as the default file encoding to ensure consistent behavior across platforms.

=== Explanation

Use `UTF-8` as the default file encoding to ensure consistent behavior across environments and avoid caching issues caused by platform-dependent default encodings.

This is especially important when working with build caching, since differences in file encoding between environments can cause unexpected cache misses.

To enforce `UTF-8` encoding, add the following to your `gradle.properties` file:

[source,properties]
----
org.gradle.jvmargs=-Dfile.encoding=UTF-8
----

NOTE: Do not rely on the default encoding of the underlying JVM or operating system, as this may differ between environments and lead to inconsistent behavior.

=== References

- <<common_caching_problems.adoc#system_file_encoding,File encoding and Caching>>.

=== Tags

`<<tags_reference.adoc#tag:properties,#properties>>`, `<<tags_reference.adoc#tag:caching,#caching>>`

[[use_build_cache]]
== Use the Build Cache

Use the Build Cache to save time by reusing outputs produced by previous builds.

=== Explanation

The Build Cache avoids re-executing tasks when their inputs haven't changed by reusing outputs from previous builds.

This prevents redundant work.
If the inputs are the same, the outputs will be too, resulting in faster, more efficient builds.

=== Example

==== Don't Do This

Build caching is disabled by default:

====
include::sample[dir="snippets/best-practices/useBuildCache-avoid/common",files="gradle.properties[]"]
====

==== Do This Instead

To enable the Build Cache, add the following to your `gradle.properties` file:

====
include::sample[dir="snippets/best-practices/useBuildCache-do/common",files="gradle.properties[]"]
====

When you build your project for the first time, Gradle populates the cache with the outputs of tasks like compilation.

Even if you run `./gradlew clean` to delete the build directory, Gradle can reuse cached outputs in subsequent builds.

[source,bash]
----
$ ./gradlew clean
----
[source,text]
----
:clean
BUILD SUCCESSFUL
----

On subsequent builds, instead of executing the `:compileJava` task again, the outputs of the task will be loaded from the Build Cache:

[source,bash]
----
$ ./gradlew compileJava
----
[source,text]
----
include::{snippetsPath}/best-practices/useBuildCache-do/tests/useBuildCache-do.secondRun.out[]
----

=== References

- <<build_cache.adoc#sec:build_cache_intro,Build Cache Overview>>

=== Tags

`<<tags_reference.adoc#tag:properties,#properties>>`, `<<tags_reference.adoc#tag:caching,#caching>>`

[[use_configuration_cache]]
== Use the Configuration Cache

Use the Configuration Cache to significantly improve build performance by caching the result of the configuration phase and reusing it in subsequent builds.

=== Explanation

The Configuration Cache works by saving the result of the configuration phase.
On the next build, if nothing relevant has changed, Gradle skips configuration entirely and loads the cached task graph from disk, jumping straight to task execution.

This can dramatically reduce build time for large builds, but it’s just as valuable for smaller builds where configuration overhead can dominate short iterations.
Faster feedback helps developers stay focused, without waiting on redundant configuration work.

It’s important to understand how this differs from the Build Cache.
The Build Cache stores the outputs of task execution, while the Configuration Cache stores the configured task graph before execution begins.
These are independent mechanisms that solve different problems, but they are designed to work together for optimal performance.

NOTE: The Configuration Cache is the preferred way to execute Gradle builds, but it is not enabled by default.
Many existing builds and plugins are not yet fully compatible, and adopting it may involve refactoring of build logic.
Enabling it by default could lead to unexpected build failures, so Gradle uses an opt-in adoption model to allow teams to verify compatibility and adopt configuration caching incrementally and safely.

=== Example

==== Don't Do This

Configuration Caching is not enabled by default:

====
include::sample[dir="snippets/best-practices/useConfigurationCache-avoid/common",files="gradle.properties[]"]
====

==== Do This Instead

To enable the Configuration Cache, add the following to your `gradle.properties` file:

====
include::sample[dir="snippets/best-practices/useConfigurationCache-do/common",files="gradle.properties[]"]
====

When you build your project for the first time, Gradle stores the outcome of the configuration phase, including the task graph, in the Configuration Cache.

[source,bash]
----
$ ./gradlew compileJava
----
[source,text]
----
Configuration cache entry stored.
include::{snippetsPath}/best-practices/useConfigurationCache-do/tests/useConfigurationCache-do.firstRun.out[]
----

On subsequent builds, instead of reconfiguring tasks like `:compileJava`, Gradle loads the task graph from the Configuration Cache and proceeds directly to execution.

[source,bash]
----
$ ./gradlew compileJava
----
[source,text]
----
Configuration cache entry reused.
include::{snippetsPath}/best-practices/useConfigurationCache-do/tests/useConfigurationCache-do.secondRun.out[]
----

=== References

- <<configuration_cache_enabling.adoc#config_cache:usage:enable,Enabling The Configuration Cache>>

=== Tags

`<<tags_reference.adoc#tag:properties,#properties>>`, `<<tags_reference.adoc#tag:caching,#caching>>`

[[avoid_computations_in_configuration_phase]]
== Avoid Expensive Computations in Configuration Phase

Avoid expensive computations in the <<build_lifecycle.adoc#build_phases,configuration phase>>, instead, move them to task actions.

=== Explanation

In order for Gradle to execute tasks it first needs to build the project task graph.
As part of discovering what tasks to include in the task graph, Gradle will configure all the tasks that are directly requested, any task dependencies of the requested tasks, and also any tasks that are not lazily registered.
This work is done in the configuration phase.

Performing expensive or slow operations such as file or network I/O, or CPU-heavy calculations in the configuration phase forces these to run even when they might be unnecessary to complete the requested work of the invoked tasks.
It is better to move these operations to task actions so that they run only when required.

=== Example

==== Don't Do This

====
include::sample[dir="snippets/best-practices/avoidComputationInConfigurationPhase-avoid/kotlin",files="build.gradle.kts[tags=avoid-this]"]
include::sample[dir="snippets/best-practices/avoidComputationInConfigurationPhase-avoid/groovy",files="build.gradle[tags=avoid-this]"]
====

<1> Performing heavy computation during configuration phase.

==== Do This Instead

====
include::sample[dir="snippets/best-practices/avoidComputationInConfigurationPhase-do/kotlin",files="build.gradle.kts[tags=do-this]"]
include::sample[dir="snippets/best-practices/avoidComputationInConfigurationPhase-do/groovy",files="build.gradle[tags=do-this]"]
====

<1> Performing heavy computation during execution phase in a task action.

=== References

- <<lazy_configuration.adoc#lazy_configuration,lazy configuration>>
- <<build_lifecycle.adoc#build_lifecycle_reference,Build Lifecycle>>

=== Tags

`<<tags_reference.adoc#tag:tasks,#tasks>>`
