Debug and optimize Android/Gradle build performance. Use when builds are slow, investigating CI/CD performance, analyzing build scans, or identifying compilation bottlenecks.
93
91%
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Advisory
Suggest reviewing before use
./gradlew assembleDebug --scan./gradlew assembleDebug --scan./gradlew assembleDebug --profile
# Opens report in build/reports/profile/./gradlew assembleDebug --info | grep -E "^\:.*"
# Or view in Android Studio: Build > Analyze APK Build| Phase | What Happens | Common Issues |
|---|---|---|
| Initialization | settings.gradle.kts evaluated | Too many include() statements |
| Configuration | All build.gradle.kts files evaluated | Expensive plugins, eager task creation |
| Execution | Tasks run based on inputs/outputs | Cache misses, non-incremental tasks |
Build scan → Performance → Build timelineCaches configuration phase across builds (AGP 8.0+):
# gradle.properties
org.gradle.configuration-cache=true
org.gradle.configuration-cache.problems=warnReuses task outputs across builds and machines:
# gradle.properties
org.gradle.caching=trueBuild independent modules simultaneously:
# gradle.properties
org.gradle.parallel=trueAllocate more memory for large projects:
# gradle.properties
org.gradle.jvmargs=-Xmx4g -XX:+UseParallelGCReduces R class size and compilation (AGP 8.0+ default):
# gradle.properties
android.nonTransitiveRClass=trueKSP is 2x faster than kapt for Kotlin:
// Before (slow)
kapt("com.google.dagger:hilt-compiler:2.51.1")
// After (fast)
ksp("com.google.dagger:hilt-compiler:2.51.1")Pin dependency versions:
// BAD: Forces resolution every build
implementation("com.example:lib:+")
implementation("com.example:lib:1.0.+")
// GOOD: Fixed version
implementation("com.example:lib:1.2.3")Put most-used repositories first:
// settings.gradle.kts
dependencyResolutionManagement {
repositories {
google() // First: Android dependencies
mavenCentral() // Second: Most libraries
// Third-party repos last
}
}Composite builds are faster than project() for large monorepos:
// settings.gradle.kts
includeBuild("shared-library") {
dependencySubstitution {
substitute(module("com.example:shared")).using(project(":"))
}
}# gradle.properties
kapt.incremental.apt=true
kapt.use.worker.api=trueDon't read files or make network calls during configuration:
// BAD: Runs during configuration
val version = file("version.txt").readText()
// GOOD: Defer to execution
val version = providers.fileContents(file("version.txt")).asTextAvoid create(), use register():
// BAD: Eagerly configured
tasks.create("myTask") { ... }
// GOOD: Lazily configured
tasks.register("myTask") { ... }Symptoms: Build scan shows long "Configuring build" time
Causes & Fixes:
| Cause | Fix |
|---|---|
| Eager task creation | Use tasks.register() instead of tasks.create() |
| buildSrc with many dependencies | Migrate to Convention Plugins with includeBuild |
| File I/O in build scripts | Use providers.fileContents() |
| Network calls in plugins | Cache results or use offline mode |
Symptoms: :app:compileDebugKotlin takes too long
Causes & Fixes:
| Cause | Fix |
|---|---|
| Non-incremental changes | Avoid build.gradle.kts changes that invalidate cache |
| Large modules | Break into smaller feature modules |
| Excessive kapt usage | Migrate to KSP |
| Kotlin compiler memory | Increase kotlin.daemon.jvmargs |
Symptoms: Tasks always rerun despite no changes
Causes & Fixes:
| Cause | Fix |
|---|---|
| Unstable task inputs | Use @PathSensitive, @NormalizeLineEndings |
| Absolute paths in outputs | Use relative paths |
Missing @CacheableTask | Add annotation to custom tasks |
| Different JDK versions | Standardize JDK across environments |
// settings.gradle.kts
buildCache {
local { isEnabled = true }
remote<HttpBuildCache> {
url = uri("https://cache.example.com/")
isPush = System.getenv("CI") == "true"
credentials {
username = System.getenv("CACHE_USER")
password = System.getenv("CACHE_PASS")
}
}
}For advanced build analytics:
// settings.gradle.kts
plugins {
id("com.gradle.develocity") version "3.17"
}
develocity {
buildScan {
termsOfUseUrl.set("https://gradle.com/help/legal-terms-of-use")
termsOfUseAgree.set("yes")
publishing.onlyIf { System.getenv("CI") != null }
}
}# Skip tests for UI-only changes
./gradlew assembleDebug -x test -x lint
# Only run affected module tests
./gradlew :feature:login:testAfter optimizations, verify:
3f68e39
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.