Zwiększona liczba metod referencyjnych po modularyzacji aplikacji

16

AS: 3.5.3; Android Gradle Plugin: 3.5.0; Stopień: 5.6.2;

Zauważyliśmy drastyczny wzrost liczby metod wymienionych w naszej aplikacji po podzieleniu modułu „app” na kilka małych modułów. Dziwne jest jednak to, że dodanie metod referencyjnych dla każdej klasy jest mniejsze niż wspomniana suma w narzędziu Android Apk Analyzer.

Dla celów testowych przeniosłem WebActivity.class z modułu „app” do modułu „adapters” i liczba metod referencyjnych wzrosła o 181 metod.

Podsumowując:

app / WebActivity = 63546 Rzeczywiste metody referencyjne, ale pokazano metody 65394 . adapter / WebActivity = 63543 Rzeczywiste metody referencyjne, ale pokazano 65575 metody .

Zauważyliśmy, że „liczba referencyjnych metod” wzrosła o prawie 10 tys. Po dodaniu / podzieleniu 4 nowych modułów.

Jaki jest dokładny problem?

Jak modularyzacja aplikacji może tak drastycznie zwiększyć liczbę metod, do których się odwołuje?

Poniżej zrzuty ekranu, które zrobiłem z dwóch różnych różnic APK-ów: WebActivity przeniesiono z modułu „aplikacji” do modułu „adaptera” i zwiększono liczbę metod referencyjnych 181:

WebActivity w module „app” wprowadź opis zdjęcia tutaj

Przeniesiono WebActivity do modułu „adaptera” wprowadź opis zdjęcia tutaj

Dlaczego na zrzutach ekranu dlaczego dodawanie metod referencyjnych przez każdą klasę (oznaczonych kolorem czerwonym) nie jest równe sumie podanej w Apk Analyzer?

Rohit Surwase
źródło
Utworzyłem problem, który można śledzić tutaj tutaj Issuetracker.google.com/issues/146957168
Rohit Surwase

Odpowiedzi:

9

Od dłuższego czasu czytam o wydajności kodu i parametrach strojenia. Rzeczywiście, jednym z moich zainteresowań są programy na Androida.

Najpierw przedstawmy podstawowe lub najważniejsze pojęcia, które pomogą nam znaleźć rozwiązanie.

Jak stwierdził programista Android

moduł można niezależnie budować, testować i debugować

W związku z tym moduły mają własne poziomy i zależności . Można je eksplorować w projekcie Hierarchy Viewer.

W rzeczywistości, modułowość kładzie nacisk na kwestie utrzymania . W przeciwieństwie do Performance Matters, ponieważ modularyzacja ma ten ważny wpływ:

  • Zwiększ głębokość dziedziczenia

Oto schemat, który nakreśliłem, aby wyjaśnić. Jak widać. Podczas korzystania z modułu dyskretnego, w celu wywołania metody A 2N micro secsporównuje się go z N micro secsmodułem dyskretnym.

wprowadź opis zdjęcia tutaj

To pytanie przyszło mi do głowy, że Metody Referencyjne liczą, co jest związane z Głębokością dziedziczenia?

Odpowiedź brzmi: chociaż użycie modularyzacji zwiększa Metodę referencyjną, ale tak naprawdę nie wpływa to na wydajność aplikacji, a głównym możliwym problemem jest głębokość dziedziczenia, w której w większości przypadków można je pominąć .

Podkreślam, że zwiększona liczba metod referencyjnych w modularyzacji wynika z każdego stopnia modułu i zależności

Jak modularyzacja aplikacji może tak drastycznie zwiększyć liczbę metod, do których się odwołuje?

Warunki, w których wpływ na analizator APK są ważne Metody referencyjne

Zwróć też uwagę, że minimalizacja i zmniejszanie kodu mogą znacznie zmienić zawartość pliku DEX po skompilowaniu kodu źródłowego.

Oprócz powyższego oficjalnego oświadczenia chcę dodać kolejny warunek, w którym wpływ analizatora APK, który:

ile doświadczenie ma programista w modularyzacji?

modularyzacja jest jak dom, w którym architektura (deweloper) określa, gdzie powinna być kuchnia, a gdzie pokój wypoczynkowy i gdzie powinna być toaleta. Co jeśli architektura zdecyduje się połączyć WC i kuchnię? Tak, to katastrofa.

Może się to zdarzyć podczas modularyzacji, jeśli deweloper nie ma dużego doświadczenia.


Odpowiadanie na pytania OP w uzupełnieniu do dodatkowych informacji

Tutaj odpowiadam na pytania operacyjne w komentarzach

Dlaczego osobny Gradle miałby dodawać do metody, do której istnieje odniesienie? Jeśli chodzi o osobną zależność, jeśli końcowy wynik to pojedynczy APK, to nie sądzę, że zduplikowane zależności w „aplikacji” i module funkcji zwiększyłyby liczbę metod, o których mowa.

Ponieważ moduły można budować, testować i debugować, MUSZĄ mieć własne poziomy i zależności.

Podczas realizacji projektu wielomodułowego kompilator generuje kilka .dexplików, w tym:

  • .dexplik dla ogółu zintegrowany zależnościami
  • moduły .dexs

.dexplik zależności to integracja wszystkich stopni modułów

Spójrzmy, jak stopień modułu wpływa na ostateczną Liczbę Mothods?

2 APK s z takim samym wynikiem, ale różnica w liczeniu metod referencyjnych.

ryc.1 Rysunek 2

Oba są pustymi działaniami, które mają 1.7króżnicę w liczbie metod referencyjnych, która jest bardzo wysoka, zależy od ich funkcjonalności. Kluczową różnicą jest stopień ich modułu, do którego skonfigurowano jednego z nich

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
}

Kolejny skonfigurowany do

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.2.0-alpha01'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta4'
}

Chociaż są to tylko puste czynności, ale spowodowana minimalna różnica w Gradle 1.7k różnicę w referencyjnych metod.

A aplikacja Gradle jest

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation project(path: ':module')
}

głównym problemem jest to, dlaczego dodawanie liczby referencyjnych metod jest inne niż łączna liczba referencyjnych metod w Apk Analyzer?

To tylko filtrowanie IDE. na pewno, jeśli wybierzesz tylko .dexplik Liczba metod referencyjnych jest równa SUMIE każdego wiersza Liczba referencyjnych metod, ale jeśli wybierzesz wiele .dexplików, zobaczysz różnicę w SUMIE i rzeczywistej liczbie, która wynika z równości w referencjach, które analizator wolał filtruj je.

na zrzutach ekranu wybrałeś wiele .dexplików, a następnie równość filtrów w analizatorze.

w naszym projekcie używamy scentralizowanego pliku dependencies.gradle, więc nie ma szans na inną wersję. Czy uważasz, że nawet jeśli mamy ten sam / dokładny zestaw zależności i ich wersji w modułach funkcji, zwiększy to liczbę metod referencyjnych?

Teoretycznie NIE powinno to zwiększać liczby referencyjnych metod. ALE , jak to wyjaśniłem, Doświadczenie programistów ma duży wpływ na końcowy wynik.

Team Analyzer powinien sprawdzić i naprawić problemy z wydajnością przed podobną wersją

  • zasady proguard
  • zmniejszone i zminimalizowane zasoby
  • androidManifest.xml
  • ustawienia stopni

Teraz chcę wyjaśnić, w jaki sposób Doświadczenie programistów i obsługa kodu wpływają na końcowy wynik. NAWET, jeśli Twój pakiet APK korzysta ze scentralizowanych zależności

Rycina 3

w powyższym przykładzie zwiększyłem Liczbę 5.1kMetod Referencyjnych NAWET JEŚLI miałem Centralne Zależności !!!!!

Jak to możliwe ?

Odpowiedź brzmi: właśnie dodałem niepotrzebny i ukryty .jarplik w libskatalogu projektu. tak łatwo, jak widać, wpłynąłem na końcowy wynik.

Jak widać Doświadczenie programistów wpływa na wynik końcowy. W rezultacie praktycznie możliwe jest, że metody referencyjne będą się zwiększać, chociaż teoretycznie NIE powinny .

I dlaczego nie ma różnicy w liczeniu metod referencyjnych, kiedy kompiluję tylko moduł „app”, wyłączając kompilację równoległą? Powinno to zmniejszyć się, ponieważ zostałyby wykorzystane tylko zależności modułu „aplikacji”, prawda?

kompilacja nie ma żadnego związku z liczonymi metodami. to zgodne z tym, co programista chce zastosować.


Wniosek

Omówiłem wszystkie możliwości związane z tym problemem. Rzeczywiście, można go wyprowadzić z różnych sytuacji, a programista, korzystając z tych wskazówek, może rozwiązać problem.

  • Mam nadzieję, że dowiedziałeś się, dlaczego Metody referencyjne zostały zwiększone i dlaczego w niektórych przypadkach można je znacznie zwiększyć.
  • Moduły mają swoje funkcje Gradle i Zależności oraz moduły zwiększania modularyzacji. dlatego te odniesienia do metod.
  • Modularyzacja faktycznie wpływa na wydajność aplikacji jako niezauważalna, ale sprawia, że ​​jej konserwacja jest znacznie lepsza.
  • Doświadczenie programistów w modularyzacji ma również duży wpływ na wynik końcowy.

WAŻNA UWAGA: prawie wszystkie oświadczenia to moje dochodzenie i badania. w rzeczywistości mogą występować błędy i usterki i zostaną zaktualizowane w celu dodania znacznie więcej informacji w przyszłości.


Mr.AF
źródło
Dzięki, panie AF, miałem nadzieję uzyskać odpowiedź po tym pytaniu, które przyszło mi do głowy, że Metody Referencyjne liczą, co jest związane z Głębokością dziedziczenia? Odpowiedź brzmi: ale nie odpowiedziałeś na to. Czy możesz wyjaśnić, dlaczego głębokość dziedziczenia zwiększa liczbę metod referencyjnych? Tak jak w naszym przypadku nie dodaliśmy żadnej dodatkowej warstwy, a jedynie podzieliliśmy moduł „app”. Istnieje szansa na zwiększenie liczby metod referencyjnych w przypadku, gdy moduł funkcji uzyskuje dostęp do metod innego modułu funkcji za pośrednictwem modułu „aplikacji”, czy to jest powód?
Rohit Surwase
Odpowiedź @RohitSurwase jest resztą instrukcji. Głębokość dziedziczenia nie zwiększa Odwołania do metod, robi to modularyzacja i modularyzacja, ponieważ głębokość dziedziczenia.
Mr.AF
@RohitSurwase, funkcja uzyskująca dostęp do innej funkcji w innym module w rzeczywistości nie zwiększa liczebności metod referencyjnych. głównym powodem wzrostu liczby referencyjnych metod jest stopień i zależności, których potrzebuje każdy moduł.
Mr.AF
@RohitSurwase wskazujesz dobre wskazówki na temat relacji moduł-moduł. w rzeczywistości, jeśli 2 moduły mają zbyt wiele relacji i metod referencyjnych, należy je połączyć, aby uzyskać lepszą wydajność. tak naprawdę moduł musi być niezależny pod względem terminu i koncepcji.
Mr.AF
1
@RohitSurwase, jak powiedziałem, nieużywany słoik może nie być twoją sprawą. Coś, co mam na myśli, jest doświadczeniem programisty i jest możliwe, że można to wyłonić z różnych źródeł. i wymieniłem wszystkie możliwe źródła, które trzeba przeszukać
Mr.AF
2

Odpowiadając na moje pytanie, ponieważ rozwiązanie właśnie kliknęło mi w głowie, chociaż nie zostało to wypróbowane, ale zadziałałoby, zdecydowanie lub najprawdopodobniej. :) Odpowiedź udzielona przez Mr.AF była bardzo przydatna do osiągnięcia ostatecznego rozwiązania. Mówi o Dlaczego? ale nie jak tego uniknąć lub jak to poprawić.

Oto sposób na odzyskanie oryginalnej / rzeczywistej liczby referencyjnych metod -

Nie zależy to od tego, jak modulizujemy aplikację, ale od tego, jak dodajemy zależności. Jeśli dodamy zależność za pomocą „ implementacji ”, ta zależność pozostanie prywatna dla modułu i żaden inny moduł nie będzie mógł jej użyć. A jeśli dodamy tę samą zależność za pomocą „ api ” (równej przestarzałej „kompilacji”), to stanie się publiczna i inne zależne moduły będą mogły z niej korzystać. Ponieważ używamy „implementacji” do dodawania zależności w każdym module w projekcie wielomodułowym, każdy moduł ma wszystkie wymagane zależności jako samodzielne, dlatego można go skompilować indywidualnie. Powoduje to skrócenie czasu kompilacji / kompilacji, ponieważ kompilowane mogą być tylko zmodyfikowane moduły. Jednak użycie „implementacji” zwiększa liczbę metod, do których istnieje odwołanieponieważ istnieje tak wiele zduplikowanych metod referencyjnych.

Jeśli więc czas kompilacji nie jest twoim problemem, ale liczba metod, o których mowa, to możesz narysować drzewo zależności wszystkich modułów i uniknąć dodawania zduplikowanej zależności, używając „api” w module podstawowym. W ten sposób nawet górny moduł może korzystać z zależności dodanej przez moduł podstawowy, co pozwoli uniknąć duplikatów. Pamiętaj, że wydłużyłoby to czas kompilacji.

Możemy osiągnąć oba, jeśli potrafimy rozróżnić zależności do debugowania i kompilacji wydania . Dodaj wszystkie zależności za pomocą „implementacji” do kompilacji debugowania i dodaj tylko wymagane i zoptymalizowane zależności do kompilacji wersji za pomocą „api” . W ten sposób kompilacja debugowania będzie szybsza, a kompilacja wydań wolniejsza, co jest przystępne.

Uwaga: zaktualizuję tę odpowiedź, gdy wymyślę, jak zapewnić osobne zależności dla debugowania i kompilacji wydania.

Rohit Surwase
źródło
Podobało mi się. dobre materiały.
Mr.AF
0

Widzę całą różnicę w twoim pakiecie „com”. Możesz rozwinąć i porównać, które dokładnie klasy się zmniejszyły. Jeśli budujesz z najnowszą wersją R8, może domyślnie usunąć część kodu. Kiedy umieścisz niektóre klasy w module zmniejszającym moduł, nie wiem, czy publiczne klasy / metody można usunąć, czy też muszą zostać w celu użycia w innym module. wprowadź opis zdjęcia tutaj

Dmitrij Samojlenko
źródło
Tak, rozwinąłem i sprawdziłem każdy pakiet, w tym „com”. Głównym problemem jest to, dlaczego dodanie liczby metod z indywidualnymi odniesieniami jest inne niż łączna liczba z referencyjnych metod w Apk Analyzer?
Rohit Surwase