skip to content

The profile report shows most time in the Configuration section. How do you interpret and act on that?

level: seniorimportance: should knowfreq 38%

answer

  1. configuration runs every build for every project
  2. tasks.register vs tasks.create
  3. lazy Provider/Property
  4. no resolution at config time
  5. configuration cache skips the phase

basics

~10 s

High Configuration time means Gradle is spending too long running build scripts and configuring tasks every build. Reduce eager work, use lazy task registration, and enable the configuration cache so configuration is reused.

solid answer

~50 s

The Configuration section measures time configuring projects — executing build-script bodies and wiring tasks — before any task runs. If it dominates, configuration work is too eager: tasks created with `tasks.create` instead of `tasks.register`, values computed eagerly instead of via `Provider`/`Property`, dependency resolution happening at configuration time, or heavy I/O in scripts. The diagnosis from the report: which projects are costly. The remedies: convert to lazy APIs so the work only runs if the task is actually needed, avoid resolving configurations during configuration, and — most impactfully — enable the **configuration cache** (`org.gradle.configuration-cache=true`), which serializes the configured task graph and skips the entire configuration phase on cache hits. After enabling it, re-profile: configuration time should collapse on the second run. The report tells you *where*; lazy APIs and the config cache are *how* you fix it.

code

kotlin · 9 lines
kotlin
// Eager (configures immediately) - bad for config time
tasks.create("report") { doLast { /* ... */ } }

// Lazy (configured only if needed)
tasks.register("report") { doLast { /* ... */ } }

// Lazy value instead of eager computation
val gitSha = providers.exec { commandLine("git", "rev-parse", "HEAD") }
    .standardOutput.asText.map { it.trim() }

go deeper

for a junior

Recognize that high Configuration time means scripts/tasks are doing too much work up front.

for a middle

Name lazy task registration and the configuration cache as the standard fixes.

for a senior

Diagnose specific causes (eager creation, config-time resolution, eager values) and verify the fix by re-profiling cached runs.

for a principal

Drive a configuration-cache rollout across modules, owning the migration of incompatible plugins/scripts and using profile data as the org-wide proof of impact.

## Why configuration time matters Gradle configures **every** project in the build on **every** invocation (unless the configuration cache is on), regardless of which tasks you requested. So configuration cost is paid even by `./gradlew help`. When the profile report's **Configuration** section dominates, you're paying that tax repeatedly. ## Reading the section It lists per-project configuration time. A few patterns: - One project far above the rest -> a specific script doing heavy work. - Broadly elevated across many projects -> a convention/`buildSrc` plugin applied everywhere doing eager work. ## Common root causes 1. **Eager task creation** — `tasks.create(...)` (or `task foo {}`) forces the task to be configured immediately. `tasks.register(...)` defers configuration until the task is actually needed. 2. **Eager value computation** — reading files, running `exec`, or computing values directly in the script instead of wrapping them in a lazy `Provider`/`Property` (`project.providers`, `objects.property<>()`). 3. **Configuration-time dependency resolution** — calling `.resolve()` / iterating a `Configuration`'s files while configuring. This both costs time and shows up in Dependency Resolution. 4. **Heavy I/O or network in scripts** — reading large files, hitting services. ## The big lever: configuration cache The **configuration cache** serializes the fully-configured task graph to disk keyed by build inputs (requested tasks, JVM args, env, files read via the providers API). On a subsequent compatible build, Gradle **reuses** that graph and skips configuration entirely — the Configuration section's cost effectively disappears on a hit. ```kotlin // gradle.properties org.gradle.configuration-cache=true ``` Making a build configuration-cache compatible also *forces* good habits: no reading mutable state at execution time, no Project access during execution, lazy wiring throughout — which independently reduces configuration time. ## Verify with the report ```bash ./gradlew build --profile # baseline # enable config cache, then: ./gradlew build --profile # run 1 stores the cache ./gradlew build --profile # run 2 should be a hit ``` Compare the Configuration numbers across the two cached runs — a hit should show near-zero configuration time. The profile report is the feedback loop that confirms your fix worked.

  • Why does configuration cost get paid even by ./gradlew help?
    Without the configuration cache, Gradle configures every project on every invocation regardless of the requested task, so configuration logic always runs.
  • How does the configuration cache eliminate this on the report?
    On a cache hit it deserializes the prebuilt task graph and skips the configuration phase, so the Configuration section's time collapses to near zero.
  • Name one habit enforced by configuration-cache compatibility.
    No access to Project (or other live build model objects) at execution time — values must be captured via lazy Provider/Property during configuration.

Configuration is like setting up the whole kitchen before cooking anything. The config cache is writing down the finished setup so next time you can start cooking immediately instead of re-arranging every pot.

saying these in an interview costs you the question

  • Suggesting tasks.create as the fix — it's the eager API you want to avoid
  • Confusing configuration cache with build cache (graph reuse vs task-output reuse)
  • Claiming configuration only runs for the requested project's subtree

context