Ten dokument pomoże Ci zidentyfikować i rozwiązać kluczowe problemy z wydajnością aplikacji.
Najważniejsze problemy z wydajnością
Istnieje wiele problemów, które mogą wpływać na wydajność aplikacji, ale Poniżej znajdziesz typowe problemy z aplikacją:
- Czas oczekiwania na uruchomienie
Czas oczekiwania na uruchomienie to czas, jaki upływa między kliknięciem aplikacji ikonę, powiadomienie lub inny punkt wejścia, a także dane użytkownika ekranu.
Staraj się realizować w swoich aplikacjach następujące cele związane ze start-upem:
Uruchomienie „na zimno” w czasie krótszym niż 500 ms. Uruchomienie zimnego startu następuje, gdy aplikacja nie ma w pamięci systemu Dzieje się tak, gdy pierwsze uruchomienie aplikacji od momentu ponownego uruchomienia lub po zatrzymaniu procesu aplikacji; przez użytkownika lub system.
Uruchomienie częściowo z pamięci następuje wtedy, gdy aplikacja jest już uruchomiona na w tle. Uruchomienie „na zimno” wymaga największego nakładu pracy systemu, ponieważ musi wczytać wszystko z pamięci i zainicjować aplikację. Spróbuj uruchomienia „na zimno” trwają maksymalnie 500 ms.
Czasy oczekiwania P95 i P99 są bardzo zbliżone do mediany czasu oczekiwania. Gdy aplikacja uruchamianie zajmuje zbyt dużo czasu, co negatywnie wpływa na wrażenia użytkowników. Komunikacja międzyprocesowa (IPC) i niepotrzebne operacje wejścia-wyjścia podczas na ścieżce krytycznej podczas uruchamiania aplikacji może wystąpić rywalizacja o blokadę. i wprowadzają niespójności.
- Zacinanie podczas przewijania
Jank to termin opisujący czkawkę, która występuje, gdy system nie jest w stanie skompilować i dostarczyć klatek w odpowiednim czasie, aby wyświetlić je ekranu z żądaną częstotliwością 60 Hz lub większą. Jank jest najbardziej widoczny, podczas przewijania strony, gdy zamiast płynnej animacji pojawiają się problemy. Janek pojawia się, gdy ruch zostanie zatrzymany w trakcie co najmniej jednej klatki, czas renderowania treści przez aplikację trwa dłużej niż długość klatki w systemie.
Aplikacje muszą być kierowane na częstotliwość odświeżania 90 Hz. Tradycyjne współczynniki renderowania to 60 Hz, ale wiele nowszych urządzeń działa w trybie 90 Hz podczas interakcji z użytkownikiem, jako przewijanie. Niektóre urządzenia obsługują jeszcze wyższe częstotliwości do 120 Hz.
Aby zobaczyć, jaka częstotliwość odświeżania jest używana przez urządzenie w danej chwili, włącz: nakładkę, korzystając z Opcji programisty > Pokaż częstotliwość odświeżania w panelu Debugowanie. .
- Przejścia, które nie są płynne
Jest to widoczne podczas interakcji, takich jak przełączanie się między kartami czy wczytywanie. nową aktywność. Takie przejścia muszą być płynnymi animacjami. np. opóźnienia lub migotanie.
- Niewydajność energii
Praca obniża poziom naładowania baterii, a wykonywanie niepotrzebnych czynności – zmniejsza zużycie baterii życia.
Przydziały pamięci, które pochodzą z tworzenia nowych obiektów w kodzie, mogą być przyczyna istotnych prac w systemie. Dzieje się tak, ponieważ alokacje wymagają wysiłku ze środowiska wykonawczego Android (ART), ale późniejsze zwolnienie tych obiektów (czyszczenie pamięci) również wymaga czasu i wysiłek. Alokacja i gromadzenie danych są znacznie szybsze i wydajniejsze, zwłaszcza w przypadku obiektów tymczasowych. Mimo że kiedyś zalecaną metodą w miarę możliwości unikaj przydzielania obiektów, zalecamy robić to, który sprawdzi się w Twojej aplikacji i architekturze. Oszczędzanie na przydziałach Ryzyko braku obsługi kodu nie jest najlepszą metodą, biorąc pod uwagę ART zdolności.
Wymaga to jednak pracy, dlatego należy pamiętać, że może przyczynić się przy przydzieleniu wielu obiektów w wewnętrznej pętli.
Zidentyfikuj problemy
Aby wykryć i rozwiązać problemy ze skutecznością, zalecamy skorzystanie z tego procesu:
- Określ i przeanalizuj te najważniejsze ścieżki użytkownika:
- Typowe procesy uruchamiania, w tym z programu uruchamiającego i powiadomień.
- Ekrany, na których użytkownik przewija dane.
- Przejścia między ekranami.
- długotrwałe procesy, takie jak nawigacja lub odtwarzanie muzyki.
- Sprawdź, co dzieje się podczas poprzednich przepływów, używając:
narzędzia do debugowania:
- Perfetto: pozwala sprawdzić, co dzieje się na urządzeniu. z dokładnymi danymi o czasie.
- Program profilujący pamięci: umożliwia sprawdzanie przeprowadzanych alokacji pamięci na stercie.
- Simpleperf: wykres flamegraficzny pokazujący, które wywołania funkcji korzystają z funkcji z największym wykorzystaniem CPU w danym okresie. Gdy zidentyfikujesz coś w Systrace zajmuje dużo czasu, ale nie wiadomo dlaczego, Simpleperf może zawierać dodatkowe informacje.
Aby zrozumieć i debugować te problemy z wydajnością, na debugowanie poszczególnych testów. Nie możesz zastąpić poprzednich kroków przez analizę danych zbiorczych. Jednak aby zrozumieć, co tak naprawdę widzą użytkownicy określać, kiedy mogą wystąpić regresje, ważne jest skonfigurowanie wskaźników. w automatycznych testach i w terenie:
- Procesy uruchamiania
- Dane pól: Czas uruchomienia Konsoli Play
- Testy laboratoryjne: testowanie startupów za pomocą Macrobenchmark
- Janek
- Dane pól
- Oto najważniejsze wskaźniki w Konsoli Play: w Konsoli Play nie możesz zawęzić do danych o konkretnej ścieżce klienta. Raportuje tylko ogólne bałagan w całej aplikacji.
- Do pomiarów niestandardowych w usłudze
FrameMetricsAggregator
: możesz stosowaćFrameMetricsAggregator
, aby rejestrować dane o zacinaniu w danym okresie procesu tworzenia kampanii.
- Testy laboratoryjne
- Przewijanie za pomocą analizy porównawczej.
- Test porównawczy gromadzi dane o czasie renderowania klatek za pomocą poleceń
dumpsys gfxinfo
które obejmują ścieżkę pojedynczego użytkownika. W ten sposób dowiesz się, z błędami w odniesieniu do konkretnej ścieżki użytkownika.RenderTime
które pozwalają określić czas renderowania klatki, jest ważne niż liczba nieprawidłowych klatek do wykrywania regresji. lub ulepszeń.
- Dane pól
Problemy z weryfikacją linków aplikacji
Linki aplikacji to precyzyjne linki oparte na adresie URL Twojej witryny, które zostały zweryfikowane należą do Twojej witryny. Oto powody, dla których link aplikacji może być wyświetlany nie powiodła się.
- Zakresy filtrów intencji: dodaj do filtrów intencji tylko parametr
autoVerify
w przypadku adresów URL, które na które aplikacja może odpowiedzieć. - Niezweryfikowane przekierowania protokołów: niezweryfikowane przekierowania po stronie serwera i subdomeny
są uznawane za
zagrożenia dla bezpieczeństwa i
nie przejdą weryfikacji. Sprawiają, że wszystkie
autoVerify
linku nie powiodło się. Na przykład w przypadku przekierowywania linków z HTTP do HTTPS takich jak example.com do www.example.com, bez weryfikacji linków HTTPS może mogą spowodować niepowodzenie weryfikacji. Pamiętaj, aby zweryfikować linki aplikacji, dodając intencję filtry. - Linki nieweryfikowalne: dodanie do testów sprawia, że system nie weryfikuje linków aplikacji.
- Niestabilne serwery: upewnij się, że serwery mogą łączyć się z aplikacjami klienckimi.
Konfigurowanie aplikacji pod kątem analizy skuteczności
Ich prawidłowa konfiguracja jest kluczowa, z aplikacji. Testowanie w systemie zbliżonym do wersji produkcyjnej a jednocześnie tłumić źródła szumu. W sekcjach poniżej znajdziesz liczbę działań związanych z pakietem APK i systemem, które możesz wykonać, aby przygotować konfigurację testu; a niektóre z nich są zależne od konkretnego przypadku użycia.
Punkty śledzenia
Aplikacje mogą instrumentować swój kod za pomocą niestandardowych zdarzeń śledzenia.
Podczas rejestrowania śladów śledzenie ta niesie ze sobą niewielkie koszty 5 μ na sekcję, więc nie umieszczaj go w każdej metodzie. Śledzenie większych fragmentów czas pracy >0,1 ms może dostarczyć znaczących informacji na temat wąskich gardeł.
Uwagi na temat plików APK
Warianty debugowania mogą być pomocne przy rozwiązywaniu problemów i symulowaniu próbek stosu,
ale mają duży wpływ na wydajność. Urządzenia z Androidem 10 (interfejs API)
na poziomie 29) i wyższych mogą używać profileable android:shell="true"
w swoich usługach
plik manifestu, który umożliwia profilowanie w kompilacji wersji.
Użyj konfiguracji zmniejszania kodu klasy produkcyjnej. W zależności od zasobów używanych przez aplikację, może to mieć znaczny wpływ na wydajność. Niektóre Konfiguracje ProGuard usuwają punkty śledzenia, więc rozważ usunięcie tych reguł dla w konfiguracji, w której prowadzisz testy.
Kompilacja
Skompiluj aplikację na urządzeniu do znanego stanu – zwykle speed
lub
speed-profile
Działania wykonywane w tle w czasie rzeczywistym (JIT) mogą mieć istotny
i zwiększa wydajność aplikacji – często osiągasz je po ponownym instalowaniu pakietu APK.
między uruchomieniami testów. Oto polecenie, które pozwala wykonać tę czynność:
adb shell cmd package compile -m speed -f com.google.packagename
Tryb kompilacji speed
całkowicie kompiluje aplikację. speed-profile
kompiluje aplikację zgodnie z profilem wykorzystywanych ścieżek kodu,
zbierane podczas korzystania z aplikacji. Konsekwentne gromadzenie profili może być trudne.
Jeśli więc zdecydujesz się na ich użycie, upewnij się, że zbierają to,
jak się wydaje. Te profile znajdują się w tej lokalizacji:
/data/misc/profiles/ref/[package-name]/primary.prof
Test porównawczy umożliwia bezpośrednie określenie trybu kompilacji.
Uwagi dotyczące systemu
W przypadku pomiarów niskopoziomowych i wysokich kalibruj urządzenia. Bieg A/B na tym samym urządzeniu i w tej samej wersji systemu operacyjnego. Mogą mieć one znaczny wpływ na użytkowników, nawet na urządzeniach tego samego typu.
Na urządzeniach z dostępem do roota rozważ użycie skryptu lockClocks
na potrzeby
Mikrotesty porównawcze Skrypty te wykonują między innymi te działania:
- Umieść procesory ze stałą częstotliwością.
- Wyłącz małe rdzenie i skonfiguruj GPU.
- Wyłącz ograniczanie termiczne.
Nie zalecamy używania skryptu lockClocks
do testów zwiększających wygodę użytkowników.
takich jak uruchamianie aplikacji,
testowanie DoU oraz zacinanie, ale może być
w mikrotestach.
W miarę możliwości korzystaj ze środowiska testowego, takiego jak Macrobenchmark, co może ograniczyć szum w pomiarach i zapobiec niedokładności pomiarów.
Powolne uruchamianie aplikacji: niepotrzebna aktywność na trampolinie
Aktywność taka może niepotrzebnie wydłużyć czas uruchamiania aplikacji.
trzeba wiedzieć, czy jest to możliwe w przypadku Twojej aplikacji. Oto przykład:
log czasu, jeden element activityStart
bezpośrednio poprzedza inny activityStart
bez żadnej ramki.
Rysunek 1. ślad przedstawiający aktywność na trampolinie.
Może się to zdarzyć zarówno w punkcie wejścia powiadomienia, jak i podczas zwykłego uruchamiania aplikacji. i często można rozwiązać ten problem przez refaktoryzację. Jeśli na przykład jesteś używając tej aktywności do konfiguracji przed inną aktywnością, uwzględnij to w komponent lub bibliotekę wielokrotnego użytku.
Niepotrzebne przydziały wyzwalające częste GC
Możesz zauważyć, że czyszczenie pamięci odbywa się częściej niż Ty jak w przypadku systemów Systrace.
W poniższym przykładzie co 10 sekund podczas długo trwającej operacji jest może wskazywać, że aplikacja może niepotrzebnie, ale stale przydzielać godzina:
Rysunek 2. Zrzut przedstawiający odstęp między zdarzeniami GC.
Możesz też zauważyć, że określony stos wywołań odpowiada za większość alokacje podczas korzystania z narzędzia Memory Profiler. Nie musisz wyeliminować wszystkich alokacje, ponieważ może to utrudniać zarządzanie kodem. Zamiast tego: zaczynają się od obszarów interaktywnych przydziałów.
Niezwykłe ramki
Proces tworzenia grafiki jest dość skomplikowany i mogą występować pewne niuanse co pozwala określić, czy użytkownik widzi klatkę do filmu. W niektórych przypadkach platforma może „ratować” i buforowanie ramki. Możesz jednak zignorować większość tych niuansów w celu identyfikacji problematycznych klatek z perspektywy aplikacji.
Jeśli aplikacja nie wymaga dużych nakładów pracy, funkcja
Punkty śledzenia Choreographer.doFrame()
występują z częstotliwością 16,7 ms przy 60 kl./s
urządzenie:
Rysunek 3. Ślad pokazujący częste szybkie klatki.
Po pomniejszeniu widoku i poruszaniu się po logu czasu klatki kluczowe były jeszcze trochę, ale nic nie szkodzi, bo nie trwa niż przydzielony czas 16,7 ms:
Rysunek 4. Ślad pokazujący częste klatki z okresowymi seriami
w naszej pracy.
Zakłócenie tego regularnego rytmu jest spowodowane nieregularną ramką, na ilustracji 5.
Rysunek 5. Śledzenie z nieprawidłową ramką.
Możesz przećwiczyć ich rozpoznawanie.
Rysunek 6. Zrzut przedstawiający więcej niedziałających klatek.
W niektórych przypadkach trzeba powiększyć punkt śledzenia, aby uzyskać więcej informacji
które liczby wyświetleń są zawyżone lub co robi RecyclerView
. W innych przypadkach
być może trzeba będzie dokładniej sprawdzić to rozwiązanie.
Więcej informacji na temat identyfikowania nieprawidłowych klatek i debugowania ich przyczyn znajdziesz w artykule Więcej informacji znajdziesz w artykule Powolne renderowanie.
Typowe błędy obiektu RecyclerView
Unieważnienie całych danych kopii zapasowej RecyclerView
może
długie czasy renderowania klatek i zacinanie się grafiki. Zamiast tego, aby zminimalizować liczbę
w widokach, które wymagają aktualizacji, unieważni tylko te dane, które uległy zmianie.
Aby dowiedzieć się, jak uniknąć kosztownych zakupów, zapoznaj się z sekcją Prezentowanie danych dynamicznych. notifyDatasetChanged()
które powodują aktualizację treści zamiast jej całkowitego zastępowania.
Jeśli nie obsługujesz poprawnie wszystkich zagnieżdżonych typów RecyclerView
, może to powodować
wewnętrzny RecyclerView
, który ma być za każdym razem całkowicie odtworzony. Każdy zagnieżdżony,
wewnętrzny RecyclerView
musi mieć ustawiony parametr RecycledViewPool
, aby zapewnić
które można poddać recyklingowi między wszystkimi wewnętrznymi elementami RecyclerView
.
Jeśli dane nie są pobierane z wyprzedzeniem lub w odpowiednim czasie, dotykanie końca listy przewijanej, gdy użytkownik musi czekać z serwera. Technicznie nie jest to zacięte, bo brak ramki możesz znacznie poprawić wygodę użytkowników, modyfikując z czasem i ilością pobierania z wyprzedzeniem, tak by użytkownik nie musiał czekać, i skalowalnych danych.
Debugowanie aplikacji
Oto różne metody debugowania wydajności aplikacji. Zobacz Ten film z omówieniem śledzenia systemu i używania Androida Program profilujący w Studio.
Debugowanie uruchamiania aplikacji przy użyciu Systrace
Informacje o procesie uruchamiania aplikacji znajdziesz w sekcji Czas uruchamiania aplikacji oraz Aby dowiedzieć się więcej o śledzeniu systemu, obejrzyj film poniżej.
Typy startupów możesz rozróżnić na następujących etapach:
- „Zimny start” – zacznij od utworzenia nowego procesu bez zapisanego stanu.
- Uruchomienie z pamięci: odtwarza aktywność podczas ponownego wykorzystania procesu lub odtwarza proces z zapisanym stanem.
- Uruchomienie z pamięci: powoduje ponowne uruchomienie aktywności i rozpoczyna się od inflacji.
Zalecamy przechwytywanie kodu przy użyciu aplikacji do śledzenia systemu na urządzeniu. W przypadku Androida 10 lub nowszego użyj Perfetto. W przypadku Androida 9 i starszych wersji użyj Systrace. Zalecamy również przeglądanie plików śledzenia za pomocą narzędzia internetowego Przeglądarka śledzenia Perfetto. Więcej informacji znajdziesz w artykule Omówienie systemu .
Zwróć uwagę na między innymi:
- Monitorowanie rywalizacji: rywalizacja o zasoby chronione monitorem może spowodować znaczne opóźnienie uruchomienia aplikacji.
Synchroniczne transakcje Binder: szukaj niepotrzebnych transakcji na na ścieżce krytycznej aplikacji. Jeśli wymagana transakcja jest kosztowna, rozważ z odpowiednim zespołem ds. platformy w celu wprowadzenia ulepszeń.
Równoczesne GC: to normalne i stosunkowo niewielki wpływ, ale jeśli często się pojawiają, rozważcie to dzięki pamięci w Android Studio. program profilujący.
I/O: sprawdź, czy podczas uruchamiania wykryto wejścia i wyjścia, i poszukaj długich przerw.
Znaczna aktywność w innych wątkach: może to zakłócać wątek UI, dlatego uważaj na pracę w tle podczas uruchamiania.
Zalecamy wywołanie metody reportFullyDrawn
po uruchomieniu
z punktu widzenia aplikacji na udoskonalenie raportowania wskaźników używanych przy uruchamianiu aplikacji. Sprawdź godzinę
na pełny ekran, aby dowiedzieć się więcej o korzystaniu z funkcji reportFullyDrawn
.
Zdefiniowane w RFD czasy rozpoczęcia można wyodrębnić za pomocą procesora śledzenia Perfetto,
i wysyłane jest zdarzenie logu czasu widoczne dla użytkownika.
Używaj śledzenia systemu na urządzeniu
Aby przechwytywać dane systemu, możesz użyć aplikacji na poziomie systemu o nazwie Monitorowanie systemu
. Ta aplikacja umożliwia rejestrowanie logów czasu z urządzenia bez
musi być podłączone do zasilania czy połączyć z urządzeniem adb
.
Używanie narzędzia Android Studio Memory Profiler
Możesz użyć narzędzia Android Studio Memory Profiler, aby sprawdzić wykorzystanie pamięci. które mogą być spowodowane wyciekami pamięci lub nieprawidłowymi wzorcami użytkowania. Zapewnia transmisję na żywo w widoku przydziałów obiektów.
Aby rozwiązać problemy z pamięcią w aplikacji, zapoznaj się z informacjami z narzędzia Memory Profiler, który pozwala śledzić, dlaczego i jak często występują GC.
Aby profilować pamięć aplikacji, wykonaj te czynności:
Wykrywaj problemy z pamięcią.
Zarejestruj sesję profilowania pamięci ścieżki użytkownika, na której chcesz się skupić. Poszukaj rosnącej liczby obiektów, tak jak na ilustracji 7, która z czasem jak widać na rys. 8.
Rysunek 7. Zwiększam liczbę obiektów.
Rysunek 8. Usuwanie odpadów.
Po zidentyfikowaniu ścieżki użytkownika, która zwiększa ilość pamięci, przeanalizuj pod kątem głównych przyczyn obniżania wydajności pamięci.
Diagnozuj największe przebarwienia pamięci.
Wybierz zakres na osi czasu, aby zwizualizować Przydziały i Płytki rozmiar, jak pokazano na ilustracji 9.
Rysunek 9. Wartości Przydziały i Płytkie Rozmiar.
Dane można sortować na kilka sposobów. Oto kilka przykładów jak każdy z nich może pomóc w analizie problemów.
Rozmieść według zajęć: przydaje się, gdy chcesz znaleźć zajęcia, które: generują obiekty, które są przechowywane w pamięci podręcznej lub używane ponownie z puli pamięci.
Jeśli na przykład widzisz, że aplikacja tworzy 2000 obiektów klasy o nazwie „Vertex” co sekundę, liczba Przydziałów wzrasta o 2000 co sekundę i można to zobaczyć przy sortowaniu według zajęć. Jeśli chcesz użyć ponownie aby uniknąć czyszczenia pamięci, zaimplementuj pulę pamięci.
Rozmieść według schematu wywołań: przydaje się, gdy chcesz znaleźć popularne miejsca. ścieżki, w której jest przydzielana pamięć, np. wewnątrz pętli lub wykonującą wiele zadań związanych z przydzielaniem.
Płytki rozmiar: śledzi tylko pamięć samego obiektu. Jest przydatna służy do śledzenia prostych klas złożonych głównie z wartości podstawowych.
Przechowywany rozmiar: pokazuje łączną ilość pamięci wiążącej się z obiektem i odwołaniami. do których odwołuje się wyłącznie obiekt. Jest przydatny do śledzenia pamięci ciśnienia spowodowanego przez złożone obiekty. Aby uzyskać tę wartość, zrób całe wspomnienie jak widać na rysunku 10, i przechowywany rozmiar jest dodawany w postaci kolumny, co pokazano na rys. 11.
Rysunek 10. Pełny zrzut pamięci.
Rysunek 11. Zachowany rozmiar.
Pomiar wpływu optymalizacji.
Wygenerowane informacje są bardziej widoczne i łatwiejsze do zmierzenia wpływu pamięci i optymalizacji. Gdy optymalizacja zmniejsza wykorzystanie pamięci, mniej GC.
Aby zmierzyć wpływ optymalizacji, na osi czasu narzędzia do profilowania należy zmierzyć między GC. Przekonasz się, że czas między kolejnymi GC potrwa dłużej.
Skutki ulepszenia pamięci są następujące:
- Wyłączenia z braku pamięci będą prawdopodobnie rzadsze, jeśli aplikacja nie będzie stale działać gdy nie wykorzystujesz pamięci.
- Mniejsza liczba zaciemniania pamięci poprawia wskaźniki zaburzeń, zwłaszcza w wersji P99. To jest ponieważ procesory GC mogą powodować rywalizację o CPU, co może prowadzić do tego, że zadania renderowania i te są odroczone w trakcie procesu GC.
Polecane dla Ciebie
- Uwaga: tekst linku wyświetla się, gdy JavaScript jest wyłączony
- Analiza i optymalizacja uruchamiania aplikacji {:#app-startup-analysis-Optimizing}
- Zablokowane klatki
- Tworzenie makroporównania