I progetti più grandi o quelli che implementano molta logica di build personalizzata
richiedono un'analisi più approfondita del processo di compilazione per individuare i colli di bottiglia.
Puoi farlo profilando il tempo impiegato da Gradle per eseguire ogni fase
il ciclo di vita e ogni attività di build. Ad esempio, se il tuo profilo build
mostra che Gradle passa troppo tempo a configurare il progetto,
suggerire che è necessario
sposta la logica di build personalizzata dalla fase di configurazione.
Inoltre, se l'attività mergeDevDebugResources
utilizza una grande quantità
del tempo di compilazione, potrebbe indicare che devi
convertire le tue immagini in WebP
o disabilita il crunching dei file PNG.
Se utilizzi Android Studio 4.0 o versioni successive: il modo migliore per esaminare il rendimento delle build problemi consiste nell'usare l'Analizzatore build.
Inoltre, sono disponibili due opzioni per la profilazione della build al di fuori Android Studio:
Lo strumento
gradle-profiler
autonomo, uno per un'analisi approfondita della tua build.L'opzione Gradle
--profile
, un pratico strumento disponibile dalla riga di comando di Gradle.
Utilizzo dello strumento autonomo gradle-profiler
Per trovare la configurazione del progetto che fornisca la migliore velocità di compilazione, dovresti usare Gradle profiler, uno strumento per raccogliere informazioni di profilazione e benchmarking per le build Gradle. Profiler Gradle consente di creare scenari di build ed eseguirli volte, prevenendo un'elevata varianza tra i risultati e garantendo la riproducibilità dei risultati.
Modalità benchmarking dovrebbe essere usato per raccogliere informazioni su build pulite e incrementali, mentre la modalità di profilazione può essere utilizzato per raccogliere informazioni più granulari sulle esecuzioni, inclusa la CPU snapshot.
Alcune configurazioni di configurazione del progetto per il benchmarking includono:
- Versioni plug-in
- Versioni Gradle
- Impostazioni JVM (dimensioni heap, dimensioni permanenti, garbage collection e così via)
- Numero di worker Gradle (
org.gradle.workers.max
) - Opzioni per plug-in per ottimizzare ulteriormente il rendimento
Per iniziare
- Installa gradle-profiler seguendo queste istruzioni
- Corsa:
gradle-profiler --benchmark --project-dir <root-project> :app:assembleDebug
Questo comando rappresenterà una build completamente aggiornata perché --benchmark
esegue
un'attività più volte senza cambiare progetto. Quindi
genera un report HTML nella directory profile-out/
che mostra
e i tempi di compilazione.
Esistono altri scenari che potrebbero essere più utili per l'analisi comparativa:
- Modifiche al codice nel corpo di un metodo in una classe in cui svolgi la maggior parte del lavoro.
- Modifiche all'API in un modulo utilizzato nel tuo progetto. Sebbene meno rispetto alle modifiche apportate al tuo codice, questo ha un impatto maggiore ed è utile per misurarlo.
- Modifiche al layout per simulare l'iterazione del lavoro dell'interfaccia utente.
- Modifiche alle stringhe per simulare la gestione di lavori di traduzione.
- Pulisci le build per simulare modifiche alla build stessa (ad es. Android Gradle
aggiornamento del plug-in, aggiornamento di Gradle o modifiche al codice di build
sotto
buildSrc
).
Per eseguire un'analisi comparativa di questi casi d'uso, potete creare uno scenario
utilizzata per guidare l'esecuzione di gradle-profiler
e che applica in modo appropriato
modifiche alle tue fonti. Puoi esaminare alcuni degli scenari comuni riportati di seguito.
Profilazione di impostazioni di memoria/CPU diverse
Per confrontare diverse impostazioni di memoria e CPU, puoi creare
più scenari che utilizzano valori diversi per org.gradle.jvmargs
. Per
Ad esempio, puoi creare scenari:
# <root-project>/scenarios.txt
clean_build_2gb_4workers {
tasks = [":app:assembleDebug"]
gradle-args = ["--max-workers=4"]
jvm-args = ["-Xmx2048m"]
cleanup-tasks = ["clean"]
}
clean_build_parallelGC {
tasks = [":app:assembleDebug"]
jvm-args = ["-XX:+UseParallelGC"]
cleanup-tasks = ["clean"]
}
clean_build_G1GC_4gb {
tasks = [":app:assembleDebug"]
jvm-args = ["-Xmx4096m", "-XX:+UseG1GC"]
cleanup-tasks = ["clean"]
}
gradle-profiler --benchmark --project-dir <root-project> --scenario-file scenarios.txt
in esecuzione
esegue tre scenari e potrai confrontare il tempo
:app:assembleDebug
richiede per ciascuna di queste configurazioni.
Profilazione di diverse versioni del plug-in Gradle
Per scoprire l'impatto della modifica della versione del plug-in Gradle tempi di creazione, crea uno scenario per l'analisi comparativa. Ciò richiede preparazione per rendere la versione del plug-in iniettabile dallo scenario. Cambia il file build.gradle principale:
# <root-project>/build.gradle
buildscript {
def agpVersion = providers.systemProperty("agpVersion").forUseAtConfigurationTime().orNull ?: '4.1.0'
ext.kotlin = providers.systemProperty('kotlinVersion').forUseAtConfigurationTime().orNull ?: '1.4.0'
dependencies {
classpath "com.android.tools.build:gradle:$agpVersion"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin"
}
}
Ora puoi specificare i plug-in Android per Gradle e Kotlin Gradle del file di scenari e chiedi allo scenario di aggiungere un nuovo metodo i file sorgente:
# <root-project>/scenarios.txt
non_abi_change_agp4.1.0_kotlin1.4.10 {
tasks = [":app:assembleDebug"]
apply-abi-change-to ["app/src/main/java/com/example/your_app/your_code_file.java,
"app/src/main/java/com/example/your_app/your_code_file.kt"]
System-properties {
"agpVersion" = "4.1.0"
"kotlinVersion" = "1.4.10"
}
non_abi_change_agp4.2.0_kotlin1.4.20 {
tasks = [":app:assembleDebug"]
apply-abi-change-to ["app/src/main/java/com/example/your_app/your_code_file.java,
"app/src/main/java/com/example/your_app/your_code_file.kt"]
System-properties {
"agpVersion" = "4.2.0-alpha16"
"kotlinVersion" = "1.4.20"
}
Profilazione di una build incrementale
La maggior parte delle build è incrementale, il che rende questa una delle più importanti scenari da profilare. Profiler Gradle offre un ampio supporto Profilare build incrementali. È in grado di applicare automaticamente modifiche a un file di origine modificando corpo del metodo, aggiungere un nuovo metodo o modificare un layout o una risorsa stringa. Per Ad esempio, puoi creare scenari incrementali come questo:
# <root-project>/scenarios.txt
non_abi_change {
tasks = [":app:assembleDebug"]
apply-non-abi-change-to = ["app/src/main/java/com/example/your_app/your_code_file.java,
"app/src/main/java/com/example/your_app/your_code_file.kt"]
}
abi_change {
tasks = [":app:assembleDebug"]
apply-abi-change-to = ["app/src/main/java/com/example/your_app/your_code_file.java,
"app/src/main/java/com/example/your_app/your_code_file.kt"]
}
layout_change {
tasks = [":app:assembleDebug"]
apply-android-layout-change-to = "app/src/main/res/your_layout_file.xml"
}
string_resource_change {
tasks = [":app:assembleDebug"]
apply-android-resource-value-change-to = "app/src/main/res/values/strings.xml"
}
gradle-profiler --benchmark --project-dir <root-project> --scenario-file scenarios.txt
in esecuzione
genera il report HTML con i dati di benchmarking.
Puoi combinare scenari incrementali con altre impostazioni, come la dimensione heap, numero di worker o versione Gradle:
# <root-project>/scenarios.txt
non_abi_change_4g {
tasks = [":app:assembleDebug"]
apply-non-abi-change-to ["app/src/main/java/com/example/your_app/your_code_file.java,
"app/src/main/java/com/example/your_app/your_code_file.kt"]
jvm-args = ["-Xmx4096m"]
}
non_abi_change_4g_8workers {
tasks = [":app:assembleDebug"]
apply-non-abi-change-to ["app/src/main/java/com/example/your_app/your_code_file.java,
"app/src/main/java/com/example/your_app/your_code_file.kt"]
jvm-args = ["-Xmx4096m"]
gradle-args = ["--max-workers=8"]
}
non_abi_change_3g_gradle67 {
tasks = [":app:assembleDebug"]
apply-non-abi-change-to ["app/src/main/java/com/example/your_app/your_code_file.java,
"app/src/main/java/com/example/your_app/your_code_file.kt"]
jvm-args = ["-Xmx3072m"]
version = ["6.7"]
}
Profilazione di una build pulita
Per eseguire il benchmarking di una build pulita, potete creare uno scenario che sarà utilizzato per guidare l'esecuzione di gradle-profiler:
# <root-project>/scenarios.txt
clean_build {
tasks = [":app:assembleDebug"]
cleanup-tasks = ["clean"]
}
Per eseguire questo scenario, utilizza il comando seguente:
gradle-profiler --benchmark --project-dir <root-project> --scenario-file scenarios.txt
Usa l'opzione Gradle --profile
Per generare e visualizzare un profilo di build dalla riga di comando Gradle, esegui segui questi passaggi:
- Apri un terminale a riga di comando nella directory principale del progetto.
- Esegui una build pulita inserendo questo comando. Durante il profilo
devi eseguire una build pulita tra una build e l'altra
perché Gradle salta le attività quando gli input in un'attività (come il codice sorgente) non
modifica. Di conseguenza, una seconda build senza modifiche agli input viene sempre eseguita più velocemente
non vengano eseguite nuovamente. Quindi, eseguendo l'attività
clean
tra le build ti permettono di profilare l'intero processo di compilazione.// On Mac or Linux, run the Gradle wrapper using "./gradlew". gradlew clean
- Eseguire una build di debug di una delle versioni di un prodotto, ad esempio "dev" sapore,
con i seguenti flag:
gradlew --profile --offline --rerun-tasks assembleFlavorDebug
-
--profile
: attiva la profilazione. -
--offline
: disattiva il recupero online da parte di Gradle delle dipendenze. Questo assicura che eventuali ritardi causati da Gradle di aggiornare le dipendenze non interferiscono con sulla profilazione dei dati. Dovresti aver già creato il progetto una volta per che Gradle abbia già scaricato e memorizzato nella cache le dipendenze. -
--rerun-tasks
: forza Gradle a eseguire nuovamente tutte le attività e a ignorare le ottimizzazioni delle attività.
-
-
Una volta completata la build, utilizza la finestra Progetto per accedere alla Directory
project-root/build/reports/profile/
(come mostrata nella figura 1). -
Fai clic con il tasto destro del mouse sul file
profile-timestamp.html
e seleziona Apri nel browser > Predefinita. Il report dovrebbe essere simile a questo come mostrato nella figura 2. Puoi esaminare ogni scheda del report per scoprire di più come la scheda Task Execution, che mostra il tempo impiegato da Gradle per eseguire ogni attività di build. -
Facoltativo:prima di apportare modifiche al progetto o alla build ripeti il comando nel passaggio 3, ma ometti Flag
--rerun-tasks
. Poiché Gradle cerca di risparmiare tempo rieseguire attività i cui input non sono cambiati (queste sono indicate comeUP-TO-DATE
nella scheda Esecuzione attività del report, come mostrato nella figura 3), puoi identificare quali attività stanno eseguendo un lavoro quando non dovrebbe esserlo. Ad esempio, se:app:processDevUniversalDebugManifest
non è contrassegnato comeUP-TO-DATE
, potrebbe suggerire che la configurazione della build sia aggiornare in modo dinamico il manifest a ogni build. Tuttavia, alcune attività devono vengono eseguiti durante ogni build, ad esempio:app:checkDevDebugManifest
.
Ora che disponi di un report sul profilo di compilazione, puoi iniziare a cercare
opportunità di ottimizzazione esaminando le informazioni in ogni scheda
report. Alcune impostazioni della build richiedono una sperimentazione perché i vantaggi possono
e differiscono tra progetti e workstation. Ad esempio, i progetti con un
il codebase può trarre vantaggio dalla riduzione del codice
per rimuovere il codice inutilizzato e ridurre le dimensioni dell'app. Tuttavia, i valori più piccoli
i progetti possono trarre vantaggio dalla disattivazione completa della riduzione del codice. Inoltre,
aumentando la dimensione dell'heap Gradle (utilizzando
org.gradle.jvmargs
) potrebbe influire negativamente sulle prestazioni delle macchine con memoria ridotta.
Dopo aver apportato una modifica alla configurazione della build, osserva i risultati le modifiche ripetendo i passaggi precedenti e generando un nuovo profilo di build. Ad esempio, la figura 4 mostra un report per la stessa app di esempio dopo l'applicazione alcune delle ottimizzazioni di base descritte in questa pagina.