Tối ưu Build
Build chậm là một trong những vấn đề phổ biến nhất khi phát triển Android. Bài viết này hướng dẫn các kỹ thuật để giảm thời gian build và cải thiện năng suất làm việc.
Tổng quan các kỹ thuật tối ưu
Phần tiêu đề “Tổng quan các kỹ thuật tối ưu”flowchart TB subgraph "🔍 Phân tích" A1["Build Scan"] A2["Profile Build"] A3["Build Analyzer"] end
subgraph "⚙️ Cấu hình" B1["gradle.properties"] B2["Daemon"] B3["Parallel Build"] end
subgraph "📦 Caching" C1["Build Cache"] C2["Configuration Cache"] C3["Incremental Build"] end
subgraph "🏗️ Module" D1["Modularization"] D2["Avoid Unused Dependencies"] end
A1 --> B1 A2 --> B2 B1 --> C1 B3 --> D1
style A1 fill:#e3f2fd style B1 fill:#e8f5e9 style C1 fill:#fff3e0 style D1 fill:#fce4ecPhân tích Build Time
Phần tiêu đề “Phân tích Build Time”Trước khi tối ưu, cần hiểu build đang chậm ở đâu.
Build Scan
Phần tiêu đề “Build Scan”# Tạo build scan./gradlew assembleDebug --scan
# Sau khi build xong, Gradle sẽ hiển thị URL để xem reportProfile Build
Phần tiêu đề “Profile Build”# Profile với báo cáo HTML./gradlew assembleDebug --profile
# Report được tạo tại:# build/reports/profile/profile-<timestamp>.htmlBuild Analyzer trong Android Studio
Phần tiêu đề “Build Analyzer trong Android Studio”- Build app: Build → Make Project
- Mở Build → Build Analyzer
- Xem chi tiết các tasks chậm
Cấu hình gradle.properties
Phần tiêu đề “Cấu hình gradle.properties”Cấu hình bộ nhớ
Phần tiêu đề “Cấu hình bộ nhớ”# Tăng heap size cho Gradle daemonorg.gradle.jvmargs=-Xmx4096m -XX:+HeapDumpOnOutOfMemoryError
# File encoding-Dfile.encoding=UTF-8
# Tránh GC pauses dài-XX:+UseParallelGCKhuyến nghị heap size:
- Dự án nhỏ: 2GB (
-Xmx2048m) - Dự án trung bình: 4GB (
-Xmx4096m) - Dự án lớn: 8GB (
-Xmx8192m)
⛔ Cảnh báo: Không set heap size quá cao nếu máy không đủ RAM. Để lại ít nhất 2GB cho hệ thống.
Parallel Execution
Phần tiêu đề “Parallel Execution”# Build các modules song songorg.gradle.parallel=true
# Số worker threads (mặc định = số CPU cores)org.gradle.workers.max=4Build Caching
Phần tiêu đề “Build Caching”# Bật build cache (cache task outputs)org.gradle.caching=true
# Configuration cache (cache configuration phase)org.gradle.configuration-cache=trueConfiguration on Demand
Phần tiêu đề “Configuration on Demand”# Chỉ configure modules cần thiếtorg.gradle.configureondemand=trueVí dụ gradle.properties tối ưu hoàn chỉnh
Phần tiêu đề “Ví dụ gradle.properties tối ưu hoàn chỉnh”# gradle.properties - Optimized for build performance
# === JVM Settings ===org.gradle.jvmargs=-Xmx4096m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC
# === Gradle Daemon ===org.gradle.daemon=true
# === Parallel & Caching ===org.gradle.parallel=trueorg.gradle.caching=trueorg.gradle.configuration-cache=trueorg.gradle.configureondemand=true
# === Android Specific ===android.useAndroidX=trueandroid.nonTransitiveRClass=trueandroid.enableJetifier=false
# === Kotlin ===kotlin.code.style=officialkotlin.incremental=trueTối ưu Dependencies
Phần tiêu đề “Tối ưu Dependencies”Tránh Dynamic Versions
Phần tiêu đề “Tránh Dynamic Versions”// ❌ Dynamic version - slow & unpredictableimplementation("com.example:library:1.+")implementation("com.example:library:latest.release")
// ✅ Fixed version - fast & predictableimplementation("com.example:library:1.2.3")Sử dụng implementation thay api
Phần tiêu đề “Sử dụng implementation thay api”// ✅ implementation: Chỉ rebuild module hiện tại khi thay đổiimplementation(libs.retrofit)
// ⚠️ api: Rebuild tất cả dependent modulesapi(libs.retrofit)Loại bỏ Dependencies không dùng
Phần tiêu đề “Loại bỏ Dependencies không dùng”Kiểm tra dependencies không sử dụng với Dependency Analysis Plugin:
plugins { id("com.autonomousapps.dependency-analysis") version "1.32.0"}./gradlew buildHealthSử dụng BOM cho compatible versions
Phần tiêu đề “Sử dụng BOM cho compatible versions”// ✅ BOM đảm bảo versions compatible, tránh conflict resolutionimplementation(platform(libs.androidx.compose.bom))implementation(libs.androidx.ui)implementation(libs.androidx.material3)Tối ưu Annotation Processing
Phần tiêu đề “Tối ưu Annotation Processing”Sử dụng KSP thay KAPT
Phần tiêu đề “Sử dụng KSP thay KAPT”KSP nhanh hơn KAPT khoảng 2x:
// ❌ KAPT - chậmplugins { id("org.jetbrains.kotlin.kapt")}dependencies { kapt(libs.room.compiler)}
// ✅ KSP - nhanhplugins { alias(libs.plugins.ksp)}dependencies { ksp(libs.room.compiler)}Các thư viện đã hỗ trợ KSP
Phần tiêu đề “Các thư viện đã hỗ trợ KSP”| Library | KSP Support |
|---|---|
| Room | ✅ Có |
| Hilt | ✅ Có |
| Moshi | ✅ Có |
| Glide | ✅ Có (glide-ksp) |
| Coil | Không cần |
Tối ưu Build Config
Phần tiêu đề “Tối ưu Build Config”Disable BuildConfig nếu không dùng
Phần tiêu đề “Disable BuildConfig nếu không dùng”android { buildFeatures { buildConfig = false // Disable nếu không dùng BuildConfig }}Disable không cần thiết
Phần tiêu đề “Disable không cần thiết”android { buildFeatures { aidl = false renderScript = false resValues = false shaders = false }}Sử dụng Non-transitive R Classes
Phần tiêu đề “Sử dụng Non-transitive R Classes”android.nonTransitiveRClass=trueĐiều này ngăn R class chứa resources từ dependencies, giảm compile time.
Tối ưu cho Debug Build
Phần tiêu đề “Tối ưu cho Debug Build”Disable Minification
Phần tiêu đề “Disable Minification”android { buildTypes { debug { isMinifyEnabled = false // Đã mặc định isShrinkResources = false } }}Sử dụng Pre-dex Libraries
Phần tiêu đề “Sử dụng Pre-dex Libraries”Với Android Gradle Plugin 8.0+, pre-dexing được bật mặc định.
Chỉ build cho kiến trúc cần thiết
Phần tiêu đề “Chỉ build cho kiến trúc cần thiết”android { defaultConfig { // Chỉ build cho emulator khi debug ndk { abiFilters += listOf("x86_64", "arm64-v8a") } }}Hoặc sử dụng split APKs:
android { splits { abi { isEnable = true reset() include("x86_64", "arm64-v8a") isUniversalApk = false } }}Tối ưu Multi-module Project
Phần tiêu đề “Tối ưu Multi-module Project”Modularization đúng cách
Phần tiêu đề “Modularization đúng cách”Chia project thành các modules nhỏ giúp incremental build hiệu quả hơn:
app/ # App module├── feature/│ ├── home/ # Feature module│ ├── profile/│ └── settings/├── core/│ ├── network/ # Core module│ ├── database/│ └── common/└── data/ └── repository/ # Data moduleSử dụng api cẩn thận
Phần tiêu đề “Sử dụng api cẩn thận”// ❌ Quá nhiều api làm chậm builddependencies { api(libs.retrofit) api(libs.gson) api(libs.okhttp)}
// ✅ Chỉ api những gì cần exposedependencies { implementation(libs.retrofit) implementation(libs.gson) api(libs.okhttp.core) // Chỉ expose OkHttp nếu cần}Tối ưu cho CI/CD
Phần tiêu đề “Tối ưu cho CI/CD”Gradle Cache
Phần tiêu đề “Gradle Cache”# GitHub Actions example- name: Cache Gradle uses: actions/cache@v4 with: path: | ~/.gradle/caches ~/.gradle/wrapper key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} restore-keys: | ${{ runner.os }}-gradle-Parallel execution
Phần tiêu đề “Parallel execution”./gradlew assembleRelease --parallel --max-workers=4Skip không cần thiết
Phần tiêu đề “Skip không cần thiết”# Skip tests khi build release./gradlew assembleRelease -x test -x lintGradle Daemon
Phần tiêu đề “Gradle Daemon”# Disable daemon trên CI (mỗi build là fresh)org.gradle.daemon=falseMonitoring Build Performance
Phần tiêu đề “Monitoring Build Performance”Build Scan
Phần tiêu đề “Build Scan”Gradle Build Scan cung cấp insights chi tiết:
./gradlew build --scanSau đó truy cập URL được cung cấp để xem:
- Task execution timeline
- Dependency resolution
- Cache hits/misses
- Build warnings
Custom performance logging
Phần tiêu đề “Custom performance logging”gradle.taskGraph.afterTask { task -> if (task.state.didWork) { println("${task.path} took ${(task.state.endTime - task.state.startTime)}ms") }}Checklist tối ưu
Phần tiêu đề “Checklist tối ưu”Cấu hình cơ bản
Phần tiêu đề “Cấu hình cơ bản”- Tăng Gradle heap size phù hợp
- Bật parallel execution
- Bật build caching
- Bật configuration cache
Dependencies
Phần tiêu đề “Dependencies”- Sử dụng fixed versions (không dùng
+hoặclatest) - Ưu tiên
implementationthayapi - Loại bỏ dependencies không dùng
- Sử dụng BOM cho thư viện families
Annotation Processing
Phần tiêu đề “Annotation Processing”- Migrate từ KAPT sang KSP
- Sử dụng incremental annotation processing
Build Features
Phần tiêu đề “Build Features”- Disable features không dùng (aidl, renderScript, etc.)
- Bật non-transitive R classes
Project Structure
Phần tiêu đề “Project Structure”- Modularize project hợp lý
- Tránh circular dependencies