Długi czas kompilacji spowalnia proces programowania. Na tej stronie opisujemy kilka metod, które mogą pomóc i rozwiązywać wąskie gardła szybkości kompilacji.
Ogólny proces zwiększania szybkości kompilacji aplikacji wygląda tak:
- Zoptymalizuj konfigurację kompilacji, wykonując kilka czynności, które od razu przyniosą korzyści większości projektów w Android Studio.
- Profiluj kompilację, aby wykryć i zdiagnozować z trudniejszymi wąskimi gardłami, które mogą być charakterystyczne dla danego projektu lub stacji.
Podczas tworzenia aplikacji wdróż ją na urządzeniu z Androidem w wersji 7.0 (poziom interfejsu API 24) lub nowszej, jeśli to możliwe. Nowsze wersje Platforma Android wprowadza lepszą mechanikę przekazywania aktualizacji aplikacji, takich jak Android Środowisko wykonawcze (ART) i natywna obsługa wielu plików DEX.
Uwaga: po pierwszej prawidłowej kompilacji możesz zauważyć, że kolejne czystą i przyrostową, działają znacznie szybciej nawet bez optymalizacje opisane na tej stronie. Dzieje się tak, ponieważ demon Gradle ma „rozgrzewkę” okres wzrostu wydajności – podobnie jak w przypadku innych rozwiązań JVM
Zoptymalizuj konfigurację kompilacji
Postępuj zgodnie z tymi wskazówkami, aby ulepszyć kompilację i szybkości projektu w Android Studio.
Zadbaj o aktualność narzędzi
Narzędzia na Androida są optymalizowane pod kątem kompilacji i otrzymują nowe funkcje. każdej aktualizacji. Kilka wskazówek na tej stronie zakłada, że używasz najnowszych wersji. Aby korzystać z najnowszych optymalizacji, zapoznaj się z tymi informacjami: do dnia:
Używaj KSP zamiast kapt
Narzędzie do przetwarzania adnotacji Kotlin (kapt) działa znacznie wolniej niż Kotlin. Procesor symboli (KSP). Jeśli tworzysz źródło Kotlin z adnotacjami i używasz narzędzi, które przetwarza adnotacje (takie jak Sala) który obsługuje KSP, przejdź na KSP.
Unikaj kompilowania niepotrzebnych zasobów
Unikaj kompilowania i pakowania zasobów, których nie testujesz, takich jak o dodatkowe lokalizacje językowe i zasoby dotyczące gęstości ekranu. Zamiast tego podaj tylko jeden element. zasoby językowe i gęstość ekranu na potrzeby Twojego programisty smaku, jak w przykładzie poniżej:
Odlotowe
android { ... productFlavors { dev { ... // The following configuration limits the "dev" flavor to using // English stringresources and xxhdpi screen-density resources. resourceConfigurations "en", "xxhdpi" } ... } }
Kotlin
android { ... productFlavors { create("dev") { ... // The following configuration limits the "dev" flavor to using // English stringresources and xxhdpi screen-density resources. resourceConfigurations("en", "xxhdpi") } ... } }
Eksperymentuj z dodaniem portalu wtyczek do Gradle na końcu
W Androidzie wszystkie wtyczki znajdują się w folderach google()
oraz
mavenCentral()
repozytoriów. Jednak Twoja kompilacja może
wymagają wtyczek innych firm, które są obsługiwane przez
gradlePluginPortal()
posprzedażna.
Gradle przeszukuje repozytoria w kolejności, w której są zadeklarowane
więc wydajność kompilacji będzie większa, jeśli wymienione repozytoria zawierają
z większości wtyczek. Dlatego eksperymentuj z gradlePluginPortal()
przez umieszczenie go jako ostatniego w bloku repozytorium w settings.gradle
. W większości przypadków pozwala to zminimalizować liczbę zbędnych wyszukiwań wtyczek
poprawia szybkość kompilacji.
Więcej informacji o tym, jak Gradle porusza się po wielu repozytoriach, znajdziesz w artykule Deklarowanie wielu repozytoriów w dokumentacji Gradle.
Używanie statycznych wartości konfiguracji kompilacji w kompilacji do debugowania
W przypadku właściwości znajdujących się w pliku manifestu lub plików zasobów zawsze używaj wartości statycznych do debugowania typu kompilacji.
Używanie dynamicznych kodów wersji, nazw wersji, zasobów lub innych elementów inna logika kompilacji, która zmienia plik manifestu, wymaga pełnej kompilacji aplikacji. za każdym razem, gdy chcesz wprowadzić zmiany, nawet jeśli rzeczywiste zmiany w przeciwnym razie wymaga jedynie wymiany „na gorąco”. Jeśli Twoja konfiguracja kompilacji wymaga takiego właściwości dynamicznych, a następnie wyodrębnij je do wariantów kompilacji wersji i zachowaj statyczne wartości kompilacji do debugowania, jak w tym przykładzie:
... // Use a filter to apply onVariants() to a subset of the variants. onVariants(selector().withBuildType("release")) { variant -> // Because an app module can have multiple outputs when using multi-APK, versionCode // is only available on the variant output. // Gather the output when we are in single mode and there is no multi-APK. val mainOutput = variant.outputs.single { it.outputType == OutputType.SINGLE } // Create the version code generating task. val versionCodeTask = project.tasks.register("computeVersionCodeFor${variant.name}", VersionCodeTask::class.java) { it.outputFile.set(project.layout.buildDirectory.file("versionCode${variant.name}.txt")) } // Wire the version code from the task output. // map will create a lazy Provider that: // 1. Runs just before the consumer(s), ensuring that the producer (VersionCodeTask) has run // and therefore the file is created. // 2. Contains task dependency information so that the consumer(s) run after the producer. mainOutput.versionCode.set(versionCodeTask.flatMap { it.outputFile.map { it.asFile.readText().toInt() } }) } ... abstract class VersionCodeTask : DefaultTask() { @get:OutputFile abstract val outputFile: RegularFileProperty @TaskAction fun action() { outputFile.get().asFile.writeText("1.1.1") } }
Zobacz przepis setVersionsFromTask na GitHubie, aby dowiedzieć się, jak ustawić kod wersji dynamicznej w projekcie.
Użyj wersji zależności statycznej
Podczas deklarowania zależności w plikach build.gradle
unikaj używania wersji dynamicznej
(takie ze znakiem plusa na końcu, np. 'com.android.tools.build:gradle:2.+'
).
Używanie dynamicznych numerów wersji może spowodować nieoczekiwane aktualizacje wersji, problemy z rozwiązaniem wersji
oraz wolniejsze kompilacje spowodowane sprawdzaniem dostępności aktualizacji przez Gradle.
Zamiast tego użyj statycznego numeru wersji.
Tworzenie modułów biblioteki
Poszukaj w aplikacji kodu, który możesz przekonwertować na moduł biblioteki Androida. Taka modularyzacja kodu pozwala systemowi kompilacji skompilować tylko modyfikować i zapisywać w pamięci podręcznej te dane wyjściowe na potrzeby przyszłych kompilacji. Modułyzacja sprawia też, równoległe wykonywanie projektów jest bardziej efektywne, włączyć tę optymalizację.
Utwórz zadania na potrzeby logiki kompilacji niestandardowej
Po utworzeniu profilu kompilacji, jeśli kompilacja
pokazuje, że stosunkowo dużo czasu kompilacji jest poświęcona **konfiguracji
na etapie projektów**, sprawdź skrypty build.gradle
i znajdź
do uwzględnienia w niestandardowym zadaniu Gradle. Przez zmianę logiki kompilacji
w zadanie, pomagasz zapewnić uruchamianie zadania tylko wtedy, gdy jest to wymagane, wyniki mogą być zapisywane w pamięci podręcznej przez
kolejnych kompilacji, które logika kompilacji będzie mogła być uruchamiana równolegle, jeśli włączysz równoległe wykonywanie projektu. Aby dowiedzieć się więcej o taks w przypadku kompilacji niestandardowej
przeczytaj oficjalną dokumentację Gradle.
Wskazówka: jeśli kompilacja zawiera dużą liczbę niestandardowych zadań, możesz
Chcesz uporządkować pliki build.gradle
, tworząc niestandardowe klasy zadań. Dodaj swoje zajęcia do
katalog project-root/buildSrc/src/main/groovy/
;
Gradle automatycznie włącza te klasy do ścieżki klasy w przypadku wszystkich
build.gradle
plików w projekcie.
Konwertuj obrazy do formatu WebP
WebP to plik graficzny, który zapewnia kompresję stratną (np. JPEG) oraz przezroczystość. (jak PNG). WebP zapewnia lepszą kompresję niż JPEG i PNG.
Zmniejszanie rozmiaru plików graficznych bez konieczności kompresji w czasie kompilacji może przyspieszyć kompilację, zwłaszcza jeśli aplikacja używa i zasobami Google Cloud. Możesz jednak zauważyć niewielki wzrost wykorzystania procesora kompresowania obrazów WebP. Łatwe korzystanie z Android Studio przekonwertuj obrazy do WebP.
Wyłącz crunching PNG
Jeśli nie przekonwertujesz pliku PNG do WebP, nadal możesz przyspieszyć kompilację, wyłączając automatyczne kompresję obrazu podczas tworzenia aplikacji.
Jeśli używasz wtyczki Androida do obsługi Gradle w wersji 3.0.0
lub nowszym, przetwarzanie plików PNG jest domyślnie wyłączone dla funkcji „debugowanie” typu kompilacji. Aby wyłączyć tę funkcję
do optymalizacji innych typów kompilacji, dodaj do pliku build.gradle
te wiersze:
Odlotowe
android { buildTypes { release { // Disables PNG crunching for the "release" build type. crunchPngs false } } }
Kotlin
android { buildTypes { getByName("release") { // Disables PNG crunching for the "release" build type. isCrunchPngs = false } } }
Rodzaje konstrukcji ani smaki produktów nie definiują tej właściwości, więc musisz
aby ręcznie ustawić tę właściwość na true
podczas tworzenia wersji
wersji Twojej aplikacji.
Eksperyment z równoległym czyszczeniem pamięci JVM
Wydajność kompilacji można poprawić, konfigurując optymalny moduł do czyszczenia pamięci JVM używany przez Gradle. Choć pakiet JDK 8 jest skonfigurowany tak, aby domyślnie używał równoległego czyszczenia pamięci, JDK 9 i nowsze wersje skonfigurowano do używania odczyszczacza G1.
Jeśli chcesz potencjalnie zwiększyć wydajność kompilacji:
testowania kompilacji Gradle za pomocą równoległego
śmieciarek. W sekcji gradle.properties
ustaw te wartości:
org.gradle.jvmargs=-XX:+UseParallelGC
Jeśli w tym polu są już ustawione inne opcje, dodaj nową:
org.gradle.jvmargs=-Xmx1536m -XX:+UseParallelGC
Aby zmierzyć szybkość kompilacji przy użyciu różnych konfiguracji, zapoznaj się z artykułem Profiluj kompilację
Zwiększ rozmiar sterty JVM
Jeśli zauważysz powolne kompilacje, a proces czyszczenia pamięci masowej zajmuje ponad 15%
czas na budowanie
Analizator kompilacji
, zwiększ rozmiar stosu wirtualnej maszyny Java (JVM).
W pliku gradle.properties
ustaw limit na 4, 6 lub 8 GB
jak w tym przykładzie:
org.gradle.jvmargs=-Xmx6g
Następnie przetestuj ją pod kątem zwiększenia szybkości kompilacji. Najprostszy sposób na określenie optymalnej sterty jest zwiększenie limitu o niewielką ilość, a następnie przetestowanie wystarczającej kompilacji i szybkości działania.
Jeśli używasz też atrybutu równoległy śmieciarek pamięci JVM, to cała linia powinna wyglądać tak:
org.gradle.jvmargs=-Xmx6g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g
Możesz przeanalizować błędy pamięci JVM, włączając funkcję HeapDumpOnOutOfMemoryError flaga włączona. Dzięki temu, gdy zabraknie pamięci, JVM wygeneruje zrzut stosu.
Użyj nieprzechodniowych klas R
Używaj nieprzechodni klas R
, aby szybciej tworzyć kompilacje
w przypadku aplikacji z wieloma modułami. Zapobiega to duplikowaniu zasobów przez zapewnienie,
klasa R
każdego modułu zawiera odwołania tylko do własnych zasobów bez pobierania odniesień
jego zależności. Przyspiesza to kompilacje i zapewnia korzyści płynące z kompilacji.
i ich unikania. Jest to domyślne zachowanie we wtyczce Androida do obsługi Gradle w wersji 8.0.0 i nowszych.
Począwszy od Android Studio Bumblebee, nieprzechodnie klasy R
są domyślnie włączone w nowych projektach.
W przypadku projektów utworzonych we wcześniejszych wersjach Android Studio zaktualizuj je, aby korzystały z nieprzechodnich
R
zajęcia, klikając Refaktoryzacja > Przeprowadź migrację do nieprzenośnych klas R.
Więcej informacji o zasobach aplikacji i klasie R
znajdziesz w artykule
Omówienie zasobów dotyczących aplikacji.
Użyj niestałych klas R
Użyj stałej klasy R
w aplikacjach i testach w celu zwiększenia przyrostu wartości kompilacji w języku Java
i pozwalają precyzyjniej ograniczać zasoby. R
pól zajęć
nie zawsze są stałe dla bibliotek, ponieważ zasoby są numerowane
podczas pakowania pakietu APK dla aplikacji lub testu zależnego od tej biblioteki.
Jest to domyślne zachowanie we wtyczce Androida do obsługi Gradle w wersji 8.0.0 i nowszych.
Wyłączanie flagi Jetifier
Większość projektów korzysta bezpośrednio z bibliotek AndroidaX, więc możesz usunąć
Jetifier, aby zwiększyć wydajność kompilacji. Aby usunąć
flagi Jetifiera, ustaw android.enableJetifier=false
w
gradle.properties
.
Analizator kompilacji może sprawdzić, czy flaga może mogą zostać bezpiecznie usunięte, aby umożliwić projektowi lepszą wydajność kompilacji i przeprowadzić migrację i nieobsługujących bibliotek pomocy Androida. Aby dowiedzieć się więcej o Analizatorze kompilacji, zobacz Rozwiązywanie problemów z wydajnością kompilacji
Użyj pamięci podręcznej konfiguracji
pamięć podręczna konfiguracji pozwala Gradle rejestrować informacje o wykresie zadań kompilacji i używać ich w kolejnych kompilacjach. Gradle nie musi ponownie konfigurować całej kompilacji.
Aby włączyć pamięć podręczną konfiguracji, wykonaj te czynności:
- Sprawdź, czy wszystkie wtyczki projektu są zgodne.
Użyj Analizator kompilacji, aby sprawdzić, czy projekt jest zgodny z pamięcią podręczną konfiguracji. Analizator kompilacji uruchamia sekwencję testów aby ustalić, czy daną funkcję można włączyć w projekcie. Zobacz numer problemu 13490: listę obsługiwanych wtyczek.
Dodaj do pliku
gradle.properties
ten kod:org.gradle.configuration-cache=true # Use this flag carefully, in case some of the plugins are not fully compatible. org.gradle.configuration-cache.problems=warn
Gdy pamięć podręczna konfiguracji jest włączona, przy pierwszym uruchomieniu projektu dane wyjściowe kompilacji
mówi Calculating task graph as no configuration cache is available for tasks
. W trakcie
w przypadku kolejnych uruchomień, wynik kompilacji to Reusing configuration cache
.
Więcej informacji o pamięci podręcznej konfiguracji znajdziesz w poście na blogu Szczegółowe omówienie buforowania konfiguracji oraz dokumentację Gradle dotyczącą funkcji pamięci podręcznej konfiguracji.
Problemy z pamięcią podręczną konfiguracji wprowadzone w Gradle 8.1 i wtyczce Androida do obsługi Gradle 8.1
Pamięć podręczna konfiguracji stała się stabilna w Gradle 8.1 i wprowadzono interfejs API plików
śledzenie konwersji. Połączenia takie jak File.exists()
, File.isDirectory()
i File.list()
są nagrywane przez
Gradle do śledzenia plików wejściowych konfiguracji.
Wtyczka Androida do obsługi Gradle (AGP) 8.1 używa tych interfejsów API File
w przypadku niektórych plików, które Gradle powinna
nie są uznawane za dane wejściowe pamięci podręcznej. Powoduje to dodatkowe unieważnienie pamięci podręcznej, gdy jest używane z
Gradle w wersji 8.1 lub nowszej, spowalnia działanie kompilacji.
W AGP 8.1 te dane są traktowane jako dane wejściowe w pamięci podręcznej:
Wprowadź tekst | Śledzenie problemów | Poprawiono w |
$GRADLE_USER_HOME/android/FakeDependency.jar | Problem nr 289232054 | AGP 8.2 |
dane wyjściowe cmake | Problem nr 287676077 | AGP 8.2 |
$GRADLE_USER_HOME/.android/analytics.settings | Problem nr 278767328 | AGP 8.3 |
Jeśli używasz tych interfejsów API lub wtyczki, która z nich korzysta, może wystąpić pogorszenie czasu kompilacji, ponieważ niektórzy z nich korzystają z tej funkcji logiki może spowodować dodatkowe unieważnienie pamięci podręcznej. Zobacz Ulepszenia śledzenia danych wejściowych konfiguracji kompilacji , aby omówić te wzorce i dowiedzieć się, jak naprawić logikę kompilacji, lub tymczasowo wyłączyć API do śledzenia plików.