Korzystanie z Analizatora konfiguracji R8

Analizator konfiguracji R8 to narzędzie, które pomaga maksymalnie wykorzystać zalety R8, dostarczając szczegółowych informacji o jakości konfiguracji aplikacji. Umożliwia śledzenie i ulepszanie optymalizacji R8 przez monitorowanie kluczowych danych, w szczególności wyników zmniejszania rozmiaru, optymalizacji i zaciemniania kodu, które wskazują odsetek bazy kodu dostępny do optymalizacji. Identyfikując ogólne lub niepotrzebne reguły zachowywania, w tym te wprowadzone przez biblioteki zewnętrzne, analizator pomaga dopracować konfigurację, aby R8 mogło skutecznie optymalizować jak najwięcej klas, pól i metod.

Generowanie raportu

W AGP w wersji 9.3.0 i nowszych możesz wygenerować raport analizatora konfiguracji R8 za pomocą samodzielnego zadania Gradle lub automatycznie podczas kompilacji R8.

Uruchamianie samodzielnego zadania Gradle (zalecane do użytku lokalnego)

Podczas aktywnego iterowania reguł zachowywania użyj samodzielnego zadania Gradle, aby szybko ocenić wpływ zmian bez pełnego tworzenia pliku APK lub pakietu:

./gradlew :app:analyzeReleaseR8Config

Ponieważ to zadanie pomija generowanie pliku APK lub pakietu, zapewnia znacznie krótszą pętlę opinii. Umożliwia to szybkie analizowanie wpływu reguł zachowywania na wyniki zmniejszania rozmiaru, optymalizacji i zaciemniania kodu oraz natychmiastowe ich dopracowywanie. Raport HTML jest generowany w app/build/reports/r8/r8-config-analyzer-release.html.

Automatyczne generowanie podczas zwykłych kompilacji

Podczas pełnej kompilacji R8 do publikacji (np. assembleRelease) raport jest automatycznie generowany w build/outputs/mapping/release/configanalyzer.html. Aby wyłączyć automatyczne generowanie danych wyjściowych podczas zwykłych kompilacji, ustaw tę właściwość Gradle:

android.experimental.r8.enableR8ConfigurationAnalyzer=false

W przypadku AGP w wersji 9.2 i starszych

W przypadku AGP w wersji 9.2 i starszych ustaw właściwość systemową com.android.tools.r8.dumpkeepradiushtmltodirectory podczas uruchamiania zadania Gradle z kompilacją włączoną w R8.

./gradlew assembleRelease \
    -Dcom.android.tools.r8.dumpkeepradiushtmltodirectory=<output_directory>

Aby na przykład wygenerować raport HTML w katalogu /tmp/r8analysis, użyj tego polecenia:

# To create the /tmp/r8analysis folder.
mkdir -p /tmp/r8analysis

# To generate the report in the /tmp/r8analysis folder.
./gradlew assembleRelease \
    -Dcom.android.tools.r8.dumpkeepradiushtmltodirectory=/tmp/r8analysis

Interpretowanie raportu

Analizator konfiguracji R8 dostarcza informacji o konfiguracji R8 aplikacji i wpływie każdej reguły zachowywania na aplikację. Pomaga to uzyskać maksymalną optymalizację z R8, co poprawia wydajność aplikacji. Użyj tych wyników, aby sprawdzić, jaka część bazy kodu jest dostępna do optymalizacji przez R8.

Przykład sekcji podsumowania raportu
Rysunek 1. Przykład sekcji podsumowania raportu.

Wynik zmniejszania rozmiaru

Gdy R8 zmniejsza rozmiar aplikacji, zmniejsza jej ogólny rozmiar, identyfikując i eliminując nieużywany kod i zasoby, dzięki czemu ostateczna kompilacja jest jak najmniejsza. Wynik zmniejszania rozmiaru śledzi odsetek klas, pól i metod, które podlegają zmniejszaniu rozmiaru. Na przykład wynik zmniejszania rozmiaru wynoszący 66% oznacza, że R8 może zmniejszyć rozmiar 66% bazy kodu.

Wynik optymalizacji

R8 przeprowadza optymalizacje, takie jak wstawianie metod i scalanie klas, co poprawia uruchamianie i wykorzystanie pamięci w aplikacji. Wynik optymalizacji śledzi odsetek klas, pól i metod, które podlegają optymalizacjom R8. Jeśli na przykład wynik optymalizacji wynosi 66%, oznacza to, że R8 może zoptymalizować tylko 66% bazy kodu.

Wynik zaciemnienia kodu

Zaciemniając klasy, pola i metody, R8 skraca ich nazwy, co zmniejsza rozmiar metadanych aplikacji i oszczędza pamięć. Wynik zaciemnienia kodu mierzy odsetek kodu dostępnego do zaciemnienia w bazie kodu.

Dopracowywanie reguł zachowywania

Aby poprawić wyniki i odblokować lepszą optymalizację R8, dopracuj reguły zachowywania, aby niepotrzebnie nie uniemożliwiały R8 optymalizacji aplikacji. Zachowuj tylko klasy, metody lub pola, do których dostęp uzyskiwany jest za pomocą refleksji.

Aby to zrobić, użyj analizy reguł zachowywania.

Przykład analizy reguły zachowywania
Rysunek 2. Przykład analizy reguł zachowywania.

Aby zobaczyć szczegółową analizę reguły, kliknij ją, aby otworzyć ekran szczegółów.

Przykład analizy reguły zachowywania
Rysunek 3. Przykład analizy reguł zachowywania.

Jak dopracować reguły zachowywania

Aby dopracować reguły zachowywania i w pełni wykorzystać potencjał optymalizacji R8 w aplikacji:

  1. W przypadku każdej reguły zachowywania sprawdź w analizatorze konfiguracji odsetek klas, pól i metod, których R8 nie może zoptymalizować. Użyj tych informacji, aby zidentyfikować reguły zachowywania, które uniemożliwiają optymalizację dużej liczby klas, pól lub metod. Wyświetlane są też właściwości optymalizacji, które są blokowane przez każdą regułę zachowywania.
  2. Jeśli widzisz regułę zachowywania, która uniemożliwia optymalizację dużej liczby klas, sprawdź, które klasy, pola i metody są blokowane przez tę regułę, aby sprawdzić, czy reguła zachowuje elementy, które nie są wywoływane dynamicznie za pomocą refleksji.
  3. Zmniejsz optymalizację blokowaną przez reguły zachowywania, kierując reklamy tylko na niezbędne klasy, pola lub metody, wybierając odpowiednią opcję zachowywania i stosując sprawdzone metody.
  4. Sprawdź i uruchom testy, które obejmują klasy, pola i metody, których dotyczy reguła zachowywania, i dopracuj reguły zachowywania.

Sprawdzanie optymalizacji bibliotek

Gdy integrujesz biblioteki zewnętrzne, często zawierają one własne reguły zachowywania, które umożliwiają współpracę z R8. Ponieważ autor biblioteki nie może przewidzieć Twojej konkretnej implementacji, czasami pisze konserwatywne, szeroko zakrojone reguły, które uniemożliwiają optymalizację większej liczby klas, pól i metod niż jest to konieczne. Może to uniemożliwić R8 optymalizację części aplikacji, które nie mają nic wspólnego z rzeczywistym wykonaniem biblioteki w czasie działania. Za pomocą analizatora konfiguracji R8 możesz identyfikować biblioteki, które wprowadzają reguły negatywnie wpływające na optymalizację aplikacji.

Użyj analizatora konfiguracji, aby sprawdzić łączny efekt wszystkich scalonych reguł zachowywania. Analizując wpływ każdej reguły zachowywania pochodzącej z biblioteki zewnętrznej, możesz identyfikować i śledzić konkretne biblioteki zewnętrzne, które uniemożliwiają optymalizację dużej części aplikacji.

Optymalizacja bibliotek

Aby rozwiązać problemy z regułami zachowywania wprowadzonymi przez biblioteki zewnętrzne:

  • Jeśli biblioteka zawiera zbyt ogólną regułę, zalecamy skontaktowanie się z osobą odpowiedzialną za jej utrzymanie i przekazanie jej danych z raportu, aby pokazać, jak bieżące reguły wpływają na wyniki optymalizacji aplikacji. Jeśli jest to biblioteka zewnętrzna, przed zgłoszeniem problemu sprawdź, czy nie ma w niej już znanych błędów.
  • W razie potrzeby możesz przetestować potencjalne ulepszenia filtrując reguły z określonej biblioteki. Możesz zaimportować reguły biblioteki do projektu, wykluczyć ogólne reguły i ponownie uruchomić analizator konfiguracji, aby zmierzyć potencjalne korzyści w zakresie rozmiaru i wydajności.

Reguły zastąpione

Może się zdarzyć, że kilka reguł zachowywania nakłada się na siebie, a jedna z nich może uniemożliwiać optymalizację w większym stopniu niż jest to konieczne. Jeśli w bazie kodu masz 2 reguły zachowywania.

# Prevents optimization in the entire package
# Remove this to improve optimization
-keep class com.example.package.** { *; }

# Prevents optimization to the class inside the package
-keep class com.example.package.Myclass

Pierwsza reguła zachowywania, która uniemożliwia optymalizację całego pakietu, zastępuje drugą regułę zachowywania, która jest kierowana na klasę w pakiecie zachowanym przez pierwszą regułę zachowywania. Gdy reguły zachowywania się nakładają, jedna z nich może blokować więcej optymalizacji niż jest to konieczne. Dopracowując te nakładające się reguły, możesz zmaksymalizować optymalizację R8 i wyeliminować dług techniczny. Ten proces polega na usprawnieniu konfiguracji, aby zachować tylko niezbędny kod, a jednocześnie w pełni wykorzystać możliwości optymalizacji R8.

Przykład sekcji podsumowania raportu
Rysunek 4. Przykład reguł zastąpionych w raporcie.

Optymalizacja reguł zastąpionych

  1. Znajdź reguły zachowywania, które zastępują inne reguły, za pomocą analizatora konfiguracji R8.
  2. Zidentyfikuj dokładne klasy, pola lub metody w bazie kodu, które faktycznie korzystają z refleksji i które należy zachować za pomocą reguł zachowywania. Dzięki temu możesz dopracować reguły zachowywania.
  3. Za pomocą analizatora konfiguracji porównaj wpływ każdej reguły, która jest kierowana na te same klasy, pola lub metody. Możesz użyć odsetka optymalizacji zablokowanej przez każdą regułę zachowywania, aby określić, która z nich jest bardziej ogólna, a która bardziej szczegółowa.
    1. Jeśli reguła szczegółowa jest napisana precyzyjnie – zachowuje tylko dokładne elementy lub klasy, do których dostęp uzyskiwany jest za pomocą refleksji – usuń regułę ogólną. Bezpiecznie odblokuje to optymalizacje R8 dla pozostałej części pakietu.
    2. Jeśli reguła ogólna jest kierowana na odpowiednie klasy, zachowaj ją i usuń regułę szczegółową. Reguła szczegółowa jest po prostu zbędna. Dopracuj regułę ogólną, aby była kierowana tylko na zidentyfikowane klasy, pola lub metody.

Sprawdź i przetestuj zmiany: ponownie uruchom analizator konfiguracji, aby upewnić się, że konflikt został rozwiązany. Następnie skompiluj kompilację do publikacji i przetestuj swoje zmiany, aby upewnić się, że baza kodu działa zgodnie z oczekiwaniami.

Usuwanie niepotrzebnych reguł

Za pomocą analizatora konfiguracji możesz systematycznie sprawdzać bazę kodu, aby identyfikować i usuwać przestarzałe reguły zachowywania, które zaśmiecają konfigurację. Analizator konfiguracji R8 wyróżnia 2 główne źródła niepotrzebnych reguł:

  • Nieużywane reguły: reguły, które nie pasują do żadnej klasy, metody ani pola w bieżącej kompilacji. Często pozostają po refaktoryzacji kodu, usunięciu zależności lub skopiowaniu i wklejeniu konfiguracji, które nie są już istotne, co niepotrzebnie komplikuje konfigurację.
  • Identyczne reguły: identyczne reguły zachowywania to reguły, które są kierowane na te same klasy, pola i metody, lub zduplikowane deklaracje reguł zachowywania w tych samych lub różnych plikach reguł zachowywania.

Oba typy reguł zaśmiecają konfigurację, co utrudnia jej utrzymanie i debugowanie. Identyfikując je, możesz zwolnić miejsce w konfiguracji.