gradle-build-performance について
gradle-build-performanceは、Gradleのビルド時間を診断・改善するためのガイダンススキルです。ビルド時間の基準を測り、Build Scanでボトルネックを特定してから、最適化を一つずつ適用する手順を示します。
主な機能
- 01クリーン・増分ビルドの時間を測定
- 02Build Scanとビルド工程を分析
- 03設定・実行・依存解決の遅延を特定
- 04キャッシュ・タスク・依存関係の最適化を提示
- 05基準値と比較して変更を検証
活用シーン
- 01ビルド時間の悪化を調査
- 02CIで不要な再コンパイルを削減
- 03設定や依存解決の遅さを診断
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ new-silvermoon/ awesome-android-agent-skills --skill gradle-build-performanceインストール後、Claude Code で/gradle-build-performanceを入力して読み込まれたか確認します。
詳細
Gradle ビルドのパフォーマンス
使用する場面
- ビルド時間が長い(クリーンビルドまたはインクリメンタルビルド)
- ビルドパフォーマンスの低下を調査する
- Gradle Build Scan を分析する
- 構成と実行のどちらがボトルネックかを特定する
- CI/CD のビルド時間を最適化する
- Gradle Configuration Cache を有効にする
- 不要な再コンパイルを減らす
- kapt/KSP のアノテーション処理をデバッグする
プロンプトの例
- 「ビルドが遅いのですが、どうすれば速くできますか?」
- 「Gradle Build Scan はどのように分析すればよいですか?」
- 「構成に時間がかかるのはなぜですか?」
- 「プロジェクトが毎回すべてを再コンパイルするのはなぜですか?」
- 「Configuration Cache を有効にするにはどうすればよいですか?」
- 「kapt が遅いのはなぜですか?」
ワークフロー
- ベースラインを測定する — クリーンビルドとインクリメンタルビルドの所要時間
- Build Scan を生成する —
./gradlew assembleDebug --scan - フェーズを特定する — 構成?実行?依存関係の解決?
- 最適化を1つ適用する — 変更をまとめて適用しないでください
- 改善を測定する — ベースラインと比較する
- Build Scan で確認する — 視覚的に確認する
クイック診断
Build 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
ビルドフェーズ
| フェーズ | 実行される処理 | よくある問題 |
|---|---|---|
| 初期化 | settings.gradle.kts を評価します | include() ステートメントが多すぎる |
| 構成 | すべての build.gradle.kts ファイルを評価します | 負荷の高いプラグイン、タスクの早期作成 |
| 実行 | 入力/出力に基づいてタスクを実行します | キャッシュミス、インクリメンタルでないタスク |
ボトルネックを特定する
Build scan → Performance → Build timeline
- 構成フェーズが長い:プラグインとビルドスクリプトの最適化に注力します
- 実行フェーズが長い:タスクのキャッシュと並列化に注力します
- 依存関係の解決が遅い:リポジトリの構成に注力します
12 の最適化パターン
1. Configuration Cache を有効にする
ビルド間で構成フェーズをキャッシュします(AGP 8.0 以降)。
# gradle.properties
org.gradle.configuration-cache=true
org.gradle.configuration-cache.problems=warn
2. ビルドキャッシュを有効にする
ビルド間およびマシン間でタスクの出力を再利用します。
# gradle.properties
org.gradle.caching=true
3. 並列実行を有効にする
独立したモジュールを同時にビルドします。
# gradle.properties
org.gradle.parallel=true
4. JVM ヒープを増やす
大規模なプロジェクトにより多くのメモリを割り当てます。
# gradle.properties
org.gradle.jvmargs=-Xmx4g -XX:+UseParallelGC
5. 非推移的な R クラスを使用する
R クラスのサイズとコンパイル時間を削減します(AGP 8.0 以降のデフォルト)。
# gradle.properties
android.nonTransitiveRClass=true
6. kapt から KSP に移行する
Kotlin では、KSP は kapt より2倍高速です。
// Before (slow)
kapt("com.google.dagger:hilt-compiler:2.51.1")
// After (fast)
ksp("com.google.dagger:hilt-compiler:2.51.1")
7. 動的な依存関係を避ける
依存関係のバージョンを固定します。
// 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")
8. リポジトリの順序を最適化する
最もよく使うリポジトリを先頭に配置します。
// settings.gradle.kts
dependencyResolutionManagement {
repositories {
google() // First: Android dependencies
mavenCentral() // Second: Most libraries
// Third-party repos last
}
}
9. ローカルモジュールには includeBuild を使用する
大規模なモノレポでは、複合ビルドのほうが project() より高速です。
// settings.gradle.kts
includeBuild("shared-library") {
dependencySubstitution {
substitute(module("com.example:shared")).using(project(":"))
}
}
10. インクリメンタルなアノテーション処理を有効にする
# gradle.properties
kapt.incremental.apt=true
kapt.use.worker.api=true
11. 構成時の I/O を避ける
構成中にファイルを読み込んだり、ネットワークを呼び出したりしないでください。
// BAD: Runs during configuration
val version = file("version.txt").readText()
// GOOD: Defer to execution
val version = providers.fileContents(file("version.txt")).asText
12. 遅延タスク構成を使用する
create() は避け、register() を使用します。
// BAD: Eagerly configured
tasks.create("myTask") { ... }
// GOOD: Lazily configured
tasks.register("myTask") { ... }
よくあるボトルネックの分析
構成フェーズが遅い
症状:Build Scan で「Configuring build」に長い時間がかかっている
原因と対処法:
| 原因 | 対処法 |
|---|---|
| タスクの早期作成 | tasks.create() の代わりに tasks.register() を使用します |
| 多数の依存関係を含む buildSrc | includeBuild を使用した Convention Plugins に移行します |
| ビルドスクリプトでのファイル I/O | providers.fileContents() を使用します |
| プラグインでのネットワーク呼び出し | 結果をキャッシュするか、オフラインモードを使用します |
コンパイルが遅い
症状::app:compileDebugKotlin に時間がかかりすぎる
原因と対処法:
| 原因 | 対処法 |
|---|---|
| インクリメンタルでない変更 | キャッシュを無効化する build.gradle.kts の変更を避けます |
| 大規模なモジュール | 小規模な機能モジュールに分割します |
| kapt の過剰な使用 | KSP に移行します |
| Kotlin コンパイラーのメモリ | kotlin.daemon.jvmargs を増やします |
キャッシュミス
症状:変更がないのにタスクが毎回再実行されます
原因と対処法:
| 原因 | 対処法 |
|---|---|
| タスク入力が不安定 | @PathSensitive、@NormalizeLineEndings を使用します |
| 出力に絶対パスが含まれている | 相対パスを使用します |
@CacheableTask がない | カスタムタスクにアノテーションを追加します |
| JDK のバージョンが異なる | 環境間で JDK を統一します |
CI/CD の最適化
リモートビルドキャッシュ
// 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")
}
}
}
Gradle Enterprise / Develocity
高度なビルド分析には、次を使用します。
// 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 }
}
}
CI で不要なタスクをスキップする
# Skip tests for UI-only changes
./gradlew assembleDebug -x test -x lint
# Only run affected module tests
./gradlew :feature:login:test
Android Studio の設定
File → Settings → Build → Gradle
- Gradle JDK:プロジェクトの JDK に合わせます
- Build and run using:Gradle(IntelliJ ではありません)
- Run tests using:Gradle
File → Settings → Build → Compiler
- Compile independent modules in parallel:✅ 有効
- Configure on demand:❌ 無効(非推奨)
検証チェックリスト
最適化後、次の項目を確認します。
- 構成キャッシュが有効で、正常に動作している
- ビルドキャッシュのヒット率が 80% を超えている(ビルドスキャンで確認)
- 動的な依存関係のバージョンを使用していない
- 可能な場合は kapt の代わりに KSP を使用している
- 並列実行が有効になっている
- JVM のメモリが適切に調整されている
- CI のリモートキャッシュが設定されている
- 構成時の I/O がない
参考資料
コメント
Markdown 対応