Typy profili i ich zastosowania

W Androidzie możesz rejestrować kilka typów profili wydajności. Zebranie profilu pomaga w debugowaniu problemów związanych z szybkością działania aplikacji, ilością używanej przez nią pamięci, zużyciem energii i innymi kwestiami.

W tym dokumencie opisujemy najbardziej przydatne typy profili oraz sytuacje, w których warto ich używać do debugowania typowych problemów z wydajnością.

Ślady systemu

Przykład śledzenia systemu
Rysunek 1.: Przykład śladu systemu.

Ślad systemu to zaawansowany profil, który zawiera informacje o procesach, wątkach, czasie, wykonywaniu zadań i procesora oraz o zdarzeniach zdefiniowanych przez system lub użytkownika.

Z perspektywy aplikacji informacje zawarte w śladach mogą obejmować szeroki zakres obszarów, w tym opóźnienia, zacięcia, pamięć, baterię i inne.

Ślady systemu zawierają te zdarzenia wywoływane przez kod, które mogą być zdefiniowane przez system lub użytkownika. Zdarzenia wywoływane przez kod to zdarzenia, które użytkownicy mogą wywoływać za pomocą wywołań funkcji.

  • Fragmenty śladu: reprezentują czas między różnymi punktami w kodzie. Można je dodawać za pomocą Trace.beginSection i Trace.endSection interfejsów API.
  • Liczniki śladu: wartości liczbowe reprezentujące dane, np. rozmiar sterty. Można je dodawać za pomocą Trace.setCounter interfejsu API.

Ślady systemu zawierają też dane, które można tworzyć na podstawie zapytań PerfettoSQL i używać do przeprowadzania analiz lub porównywania śladów.

Zalecamy używanie śladów systemu do wykonywania tych zadań:

  • Diagnozowanie problemów z opóźnieniami. Śledzenie systemu doskonale nadaje się do znajdowania problemów z opóźnieniami spowodowanych opóźnieniami, oczekiwaniem lub problemami z planowaniem. Inne profilerzy, np. profile oparte na próbkach, nie dostarczają informacji o czasie, które zawierają ślady systemu.

  • Znajdowanie zduplikowanych obliczeń. Śledzenie może ujawnić, czy niektóre obliczenia są powtarzane, co może wskazywać na niepotrzebne operacje.

  • Diagnozowanie problemów z rywalizacją o blokady. Dzięki informacjom o stanach wątków i fragmentach pokazujących, kiedy zasoby są zablokowane, możesz sprawdzić, czy blokady (np. bloki synchronized) powodują opóźnienia w ścieżkach użytkowników.

  • Poznawanie wielowątkowości w aplikacji. Ślady oferują widok wielu wątków, pokazując stan każdego wątku i wszystkie fragmenty śladu dodane przez system lub aplikację. Ten widok wielowątkowy pomaga zrozumieć, które wątki są aktywne, które są w stanie uśpienia, co robią i jak ze sobą współdziałają.

  • Przeprowadzanie złożonych analiz wydajności. Dzięki zaawansowanemu interfejsowi użytkownika i możliwości wyświetlania różnych typów informacji ślady systemu są przydatne do debugowania wielu problemów z wydajnością, w tym opóźnień, pamięci i wykorzystania baterii.

Ślady systemu obsługują też wykonywanie zapytań za pomocą PerfettoSQL. Ta zaawansowana funkcja umożliwia:

  • wyodrębnianie określonych danych;
  • przekształcanie danych śladu w dane niestandardowe;
  • tworzenie ścieżek debugowania na podstawie zapytań, aby ułatwić wizualizację najważniejszych elementów w interfejsie Perfetto;
  • przeprowadzanie złożonych analiz bezpośrednio w interfejsie Perfetto.

Profile próbek stosu

Przykładowy profil próbki stosu
Rysunek 2.: Przykład profilu próbek stosu.

Profile próbek stosu działają przez rejestrowanie próbek wykonywania kodu i przechowywanie informacji o stosie wywołań z określoną częstotliwością, gdy wątek wykonuje zadania na procesorze. Dzięki temu możesz dowiedzieć się, co robi Twój kod podczas wykonywania.

Zalecamy używanie próbek stosu do tych czynności:

  • Optymalizacja punktów aktywności. Próbki stosu pomagają identyfikować części kodu z dużą aktywnością procesora, co oznacza, że wątek często jest w stanie „działania”.
  • Poznawanie wykonywania kodu. Próbki stosu mogą pomóc w zrozumieniu ogólnego zachowania bazy kodu.
  • Identyfikowanie kodu, który nie powinien być wykonywany. Możesz znaleźć stosy wywołań, które w ogóle nie powinny być wykonywane, co wskazuje na natychmiastowe możliwości optymalizacji.

Zrzuty sterty

Przykład zrzutu sterty
Rysunek 3.: Przykład zrzutu sterty.

Zrzuty sterty Java pokazują migawkę sterty pamięci Java aplikacji. Ta migawka zawiera wszystkie obiekty i sposób, w jaki się do siebie odnoszą w momencie wykonania zrzutu.

Zalecamy zbieranie zrzutów sterty, aby:

  • Odkrywać zduplikowane obiekty. Zrzuty sterty pokazują liczbę aktywnych obiektów, co jest przydatne do śledzenia zduplikowanych obiektów. Zawierają też odniesienia do obiektów, co pomaga określić lokalizację kodu, w której zostały utworzone obiekty.
  • Znajdować wycieki pamięci. Zrzuty sterty mogą ujawnić pamięć, która nie powinna być już używana w momencie wykonania zrzutu, co wskazuje na potencjalne wycieki pamięci.
  • Identyfikować obiekty, które można zoptymalizować. Zrzuty sterty pokazują obiekty, które używają dużo pamięci, oraz ich liczbę, co pomaga identyfikować nieefektywne wzorce użycia pamięci.

Profile sterty

Przykład profilu sterty
Rysunek 4.: Przykład profilu sterty.

Profile sterty są dostępne w wersjach natywnych i Java i doskonale nadają się do debugowania problemów z pamięcią. Są podobne do próbek stosu wywołań, ale zamiast mierzyć cykle procesora, pobierają próbki, gdy przydzielana jest pamięć.

Zalecamy używanie profili sterty do tych czynności:

  • Ograniczanie zużycia pamięci. Profile sterty zawierają próbki z lokalizacjami kodu przydziału pamięci. Pomaga to identyfikować obszary, które tworzą wiele obiektów tymczasowych, co może przyczyniać się do częstego odśmiecania pamięci w aplikacji.
  • Odkrywanie wycieków pamięci. Profile sterty można używać z innymi profilami pamięci do diagnozowania i naprawiania wycieków pamięci. Pomagają one określić lokalizacje, które przydzielają znacznie więcej pamięci niż oczekiwano.

Łączenie profili

Często analizujesz wydajność za pomocą jednego profilu. Jednak zebranie kilku profili lub jednego profilu połączonego może często dać pełniejszy obraz i pomóc w diagnozowaniu złożonych problemów, których nie można rozwiązać za pomocą jednego profilu.

Oto scenariusze, w których łączenie profili jest korzystne:

  • Scenariusz 1. Badanie kodu bez instrumentacji. Ślad systemu może pokazywać opóźnienia w przypadku operacji, które zostały już zinstrumentowane. Możesz jednak potrzebować więcej informacji o częściach kodu bez instrumentacji, które są wykonywane w tym czasie. Aby to sprawdzić, utwórz profil stosu wywołań, aby poznać wykonywany kod. Te informacje mogą pomóc w ulepszeniu śledzenia przez dodanie większej liczby fragmentów śladu.

  • Scenariusz 2. Analizowanie wycieków pamięci i odśmiecania pamięci. Wyobraź sobie, że ślad systemu pokazuje stały wzrost sterty pamięci Java z powodu przydziałów, co powoduje częste odśmiecanie pamięci. Aby poznać przydzielone obiekty, utwórz profil sterty lub zrzut sterty. To połączone podejście pomaga identyfikować sposoby zmniejszenia wykorzystania pamięci. Na przykład zmniejszenie marnotrawnych lub optymalnych przydziałów za pomocą buforowania może zapobiec odśmiecaniu pamięci.