Użyj narzędzia Simpleperf, aby ocenić wydajność urządzenia. Simpleperf to natywne narzędzie do profilowania aplikacji i procesów natywnych na Androidzie. Użyj profilera procesora, aby sprawdzać wykorzystanie procesora przez aplikację i aktywność wątków w czasie rzeczywistym.
Istnieją 2 widoczne dla użytkownika wskaźniki wydajności:
- Przewidywalna, zauważalna skuteczność Czy interfejs użytkownika gubi klatki lub renderuje obraz w sposób ciągły z częstotliwością 60 klatek na sekundę? Czy dźwięk jest odtwarzany bez artefaktów i trzasków? Jak długie jest opóźnienie między dotknięciem ekranu przez użytkownika a wyświetleniem efektu?
- Czas potrzebny na dłuższe operacje (np. otwieranie aplikacji).
Pierwszy jest bardziej widoczny niż drugi. Użytkownicy zwykle zauważają zacinanie się, ale nie są w stanie odróżnić czasu uruchamiania aplikacji wynoszącego 500 ms od 600 ms, chyba że porównują dwa urządzenia obok siebie. Opóźnienie dotyku jest od razu zauważalne i ma znaczący wpływ na postrzeganie urządzenia.
Dlatego w przypadku szybkiego urządzenia potok interfejsu użytkownika jest najważniejszym elementem systemu, poza tym, co jest niezbędne do jego działania. Oznacza to, że potok interfejsu powinien mieć wyższy priorytet niż inne zadania, które nie są niezbędne do płynnego działania interfejsu. Aby zapewnić płynność interfejsu, synchronizacja w tle, dostarczanie powiadomień i podobne działania muszą być opóźnione, jeśli można uruchomić działania interfejsu. Można poświęcić wydajność dłuższych operacji (czas działania HDR+, uruchamianie aplikacji itp.), aby zachować płynność interfejsu.
Przepustowość a jitter
Podczas oceny wydajności urządzenia przepustowość i jitter to 2 istotne dane.
Pojemność
Pojemność to łączna ilość danego zasobu, którą urządzenie posiada w określonym czasie. Mogą to być zasoby procesora, zasoby GPU, zasoby wejścia/wyjścia, zasoby sieciowe, przepustowość pamięci lub dowolne podobne dane. Podczas analizowania wydajności całego systemu warto odseparować poszczególne komponenty i przyjąć pojedynczy wskaźnik określający wydajność (zwłaszcza podczas dostrajania nowego urządzenia, ponieważ obciążenia uruchamiane na tym urządzeniu są prawdopodobnie stałe).
Pojemność systemu zależy od dostępnych zasobów obliczeniowych. Zmiana częstotliwości procesora lub GPU to podstawowy sposób zmiany pojemności, ale istnieją też inne, np. zmiana liczby rdzeni procesora online. W związku z tym pojemność systemu odpowiada zużyciu energii. Zmiana pojemności zawsze powoduje podobną zmianę zużycia energii.
Wymagana w danym momencie moc obliczeniowa jest w ogromnej większości określana przez uruchomioną aplikację. W rezultacie platforma ma niewielkie możliwości dostosowania mocy obliczeniowej wymaganej do wykonania danego zbioru zadań, a sposoby na to są ograniczone do ulepszeń środowiska wykonawczego (framework Androida, ART, Bionic, kompilator/sterowniki GPU, jądro).
Zakłócenia
Wymaganą pojemność dla obciążenia można łatwo sprawdzić, ale jitter to bardziej niejasne pojęcie. Aby dobrze poznać problem drgań jako przeszkody w szybkich systemach, zalecamy przeczytanie artykułu The Case of the Missing Supercomputer Performance: Achieving Optimal Performance on the 8,192 processors of ASCI Q (w języku angielskim). (To analiza przyczyn, dla których superkomputer ASCI Q nie osiągnął oczekiwanej wydajności. Jest to świetne wprowadzenie do optymalizacji dużych systemów).
Na tej stronie używamy terminu jitter na określenie tego, co w artykule ASCI Q nazywa się szumem. Jitter to losowe zachowanie systemu, które uniemożliwia wykonywanie zauważalnej pracy. Często jest to praca, którą trzeba wykonać, ale nie musi ona mieć ścisłych wymagań czasowych, które powodują, że jest wykonywana w określonym czasie. Ponieważ jest on losowy, bardzo trudno jest obalić istnienie wahań w przypadku danego obciążenia. Bardzo trudno jest też udowodnić, że znane źródło jittera było przyczyną konkretnego problemu z wydajnością. Narzędzia najczęściej używane do diagnozowania przyczyn wahań (np. śledzenie lub rejestrowanie) mogą same powodować wahania.
Źródła drgań w rzeczywistych wdrożeniach Androida to:
- Opóźnienie harmonogramu
- Moduły obsługi przerwań
- Kod sterownika działa zbyt długo z wywłaszczaniem lub przerwaniami wyłączonymi
- Długotrwałe przerwania programowe
- Rywalizacja o blokadę (aplikacja, platforma, sterownik jądra, blokada usługi Binder, blokada mmap)
- Konflikt deskryptora pliku, w którym wątek o niskim priorytecie blokuje plik, uniemożliwiając uruchomienie wątku o wysokim priorytecie.
- Uruchamianie kodu krytycznego dla interfejsu w kolejkach zadań, w których może on być opóźniony
- Przejścia w stan bezczynności procesora
- Logowanie
- Opóźnienia wejścia/wyjścia
- Tworzenie niepotrzebnych procesów (np. transmisje
CONNECTIVITY_CHANGE
) - Wymiana pamięci podręcznej strony spowodowana niewystarczającą ilością wolnej pamięci
Wymagany czas dla danego okresu wahań może się zmniejszać lub nie, w miarę jak zwiększa się pojemność. Jeśli na przykład sterownik pozostawi przerwania wyłączone podczas oczekiwania na odczyt z magistrali i2c, zajmie to stałą ilość czasu niezależnie od tego, czy procesor działa z częstotliwością 384 MHz czy 2 GHz. Zwiększenie przepustowości nie jest dobrym rozwiązaniem, gdy chcesz poprawić wydajność w przypadku występowania wahań. W rezultacie szybsze procesory zwykle nie poprawiają wydajności w sytuacjach, w których występuje ograniczenie związane z jitterem.
W przeciwieństwie do przepustowości zakłócenia są niemal w całości zależne od dostawcy systemu.
Zużycie pamięci
Za słabą wydajność tradycyjnie obwinia się zużycie pamięci. Samo zużycie nie jest problemem z wydajnością, ale może powodować wahania z powodu obciążenia narzędzia lowmemorykiller, ponownego uruchamiania usług i przepełnienia pamięci podręcznej strony. Zmniejszenie zużycia pamięci może zapobiec bezpośrednim przyczynom słabej wydajności, ale mogą istnieć inne ukierunkowane ulepszenia, które również pozwolą uniknąć tych przyczyn (np. przypięcie struktury, aby zapobiec jej wyładowaniu z pamięci, gdy wkrótce będzie potrzebna).
Analizowanie początkowej wydajności urządzenia
Rozpoczynanie od działającego, ale słabo działającego systemu i próba naprawienia jego działania poprzez analizowanie poszczególnych przypadków słabego działania widocznego dla użytkownika nie jest dobrą strategią. Słaba wydajność zwykle nie jest łatwa do odtworzenia (np. jitter) lub jest problemem z aplikacją, a zbyt wiele zmiennych w pełnym systemie uniemożliwia skuteczność tej strategii. W efekcie bardzo łatwo jest błędnie zidentyfikować przyczyny problemów i wprowadzić drobne ulepszenia, a jednocześnie przeoczyć systemowe możliwości poprawy wydajności w całym systemie.
Zamiast tego podczas uruchamiania nowego urządzenia postępuj w ten sposób:
- Uruchom system w interfejsie użytkownika ze wszystkimi sterownikami i podstawowymi ustawieniami regulatora częstotliwości (jeśli zmienisz ustawienia regulatora częstotliwości, powtórz wszystkie czynności poniżej).
- Upewnij się, że jądro obsługuje
sched_blocked_reason
punkt śledzenia, a także inne punkty śledzenia w potoku wyświetlania, które wskazują, kiedy ramka jest dostarczana na wyświetlacz. - Wykonaj długie śledzenie całego potoku interfejsu (od otrzymania danych wejściowych przez IRQ do końcowego skanowania) podczas wykonywania lekkiego i spójnego zadania (np. UiBench lub testu z piłką w TouchLatency).
- Rozwiąż problemy ze spadkami liczby klatek wykryte w lekkim i spójnym zadaniu.
- Powtarzaj kroki 3–4, aż będziesz w stanie nagrywać przez ponad 20 sekund bez utraty klatek.
- Przejdź do innych źródeł zacięć widocznych dla użytkownika.
Inne proste czynności, które możesz wykonać na wczesnym etapie uruchamiania urządzenia:
- Upewnij się, że jądro zawiera łatkę punktu śledzenia sched_blocked_reason. Ten punkt śledzenia jest włączony w kategorii śledzenia sched w narzędziu systrace i wskazuje funkcję odpowiedzialną za uśpienie, gdy wątek przechodzi w stan nieprzerwanego uśpienia. Ma to kluczowe znaczenie w przypadku analizy wydajności, ponieważ nieprzerwany sen jest bardzo częstym wskaźnikiem wahań.
- Upewnij się, że masz wystarczające śledzenie potoków GPU i wyświetlania. Na nowszych układach SOC firmy Qualcomm punkty śledzenia są włączane za pomocą tego polecenia:
adb shell "echo 1 > /d/tracing/events/kgsl/enable"
adb shell "echo 1 > /d/tracing/events/mdss/enable"
Te zdarzenia pozostają włączone podczas uruchamiania narzędzia systrace, dzięki czemu w śladzie możesz zobaczyć dodatkowe informacje o potoku wyświetlania (MDSS) w sekcji mdss_fb0
. W przypadku układów SOC firmy Qualcomm w standardowym widoku systrace nie zobaczysz żadnych dodatkowych informacji o procesorze graficznym, ale wyniki są obecne w samym śladzie (szczegółowe informacje znajdziesz w artykule Understanding systrace).
W przypadku tego rodzaju śledzenia wyświetlania zależy Ci na jednym zdarzeniu, które bezpośrednio wskazuje, że klatka została dostarczona na wyświetlacz. Na tej podstawie możesz określić, czy udało Ci się osiągnąć odpowiedni czas klatki.Jeśli zdarzenie Xn występuje mniej niż 16,7 ms po zdarzeniu Xn-1 (przy założeniu, że wyświetlacz ma częstotliwość odświeżania 60 Hz), oznacza to, że nie wystąpiło zacinanie. Jeśli Twój SOC nie udostępnia takich sygnałów, poproś o nie dostawcę. Debugowanie drgań jest niezwykle trudne bez jednoznacznego sygnału zakończenia klatki.
Korzystanie z syntetycznych testów porównawczych
Testy syntetyczne są przydatne do sprawdzania podstawowych funkcji urządzenia. Traktowanie testów porównawczych jako przybliżonego wskaźnika postrzeganej wydajności urządzenia nie jest jednak przydatne.
Z naszych doświadczeń z układami SOC wynika, że różnice w wynikach testów syntetycznych między układami SOC nie są skorelowane z podobnymi różnicami w odczuwalnej wydajności interfejsu (liczba pominiętych klatek, czas klatki w 99 percentylu itp.). Testy syntetyczne to testy porównawcze dotyczące tylko przepustowości. Drgania wpływają na zmierzoną wydajność tych testów porównawczych tylko przez zabieranie czasu z operacji zbiorczej testu porównawczego. W rezultacie syntetyczne wyniki testów porównawczych są w większości przypadków nieistotne jako miara wydajności odczuwanej przez użytkownika.
Rozważmy 2 układy SOC, które uruchamiają test porównawczy X renderujący 1000 klatek interfejsu i podający łączny czas renderowania (im niższy wynik, tym lepiej).
- SOC 1 renderuje każdą klatkę testu porównawczego X w 10 ms i uzyskuje wynik 10 000.
- SOC 2 renderuje 99% klatek w 1 ms,ale 1% klatek w 100 ms i uzyskuje wynik 19 900, czyli znacznie lepszy.
Jeśli test porównawczy wskazuje na rzeczywistą wydajność interfejsu, SOC 2 będzie bezużyteczny. Przy założeniu częstotliwości odświeżania 60 Hz SOC 2 będzie miał zacinającą się klatkę co 1, 5 s działania. W tym czasie SOC 1 (wolniejszy SOC według Benchmark X) działałby płynnie.
Korzystanie z raportów o błędach
Raporty o błędach są czasami przydatne do analizy wydajności, ale ponieważ są bardzo obszerne, rzadko pomagają w debugowaniu sporadycznych problemów z zacinaniem się. Mogą one zawierać wskazówki dotyczące tego, co system robił w danym momencie, zwłaszcza jeśli problem wystąpił w trakcie przechodzenia między aplikacjami (co jest rejestrowane w raporcie o błędach). Raporty o błędach mogą też wskazywać, kiedy coś jest nie tak z systemem, co może zmniejszyć jego efektywną pojemność (np. ograniczenie termiczne lub fragmentacja pamięci).
Używanie TouchLatency
Kilka przykładów nieprawidłowego działania pochodzi z TouchLatency, czyli preferowanego okresowego obciążenia używanego w przypadku Pixela i Pixela XL. Jest dostępny na stronie
frameworks/base/tests/TouchLatency
i ma 2 tryby: opóźnienie dotyku i odbijająca się piłka (aby przełączać tryby, kliknij przycisk w prawym górnym rogu).
Test z piłką odbijającą się jest tak prosty, jak się wydaje: piłka odbija się po ekranie w nieskończoność, niezależnie od działań użytkownika. Jest to zwykle zdecydowanie najtrudniejszy test do przeprowadzenia bezbłędnie, ale im bliżej jest do uruchomienia bez utraty klatek, tym lepsze będzie Twoje urządzenie. Test z odbijającą się piłką jest trudny, ponieważ jest to trywialne, ale doskonale spójne obciążenie, które działa przy bardzo niskim taktowaniu (zakładamy, że urządzenie ma regulator częstotliwości; jeśli urządzenie działa ze stałym taktowaniem, przy pierwszym uruchomieniu testu z odbijającą się piłką obniż taktownie procesora lub procesora graficznego do wartości zbliżonej do minimalnej). W miarę wyciszania systemu i zmniejszania częstotliwości zegara do poziomu zbliżonego do stanu bezczynności wymagany czas procesora/karty graficznej na klatkę wzrasta. Możesz obserwować piłkę i zauważyć, że obraz się zacina. W narzędziu systrace zobaczysz też pominięte klatki.
Ponieważ obciążenie jest tak spójne, możesz łatwiej niż w przypadku większości obciążeń widocznych dla użytkownika zidentyfikować większość źródeł wahań, śledząc, co dokładnie działa w systemie podczas każdej pominiętej klatki, zamiast śledzić potok interfejsu. Niższe częstotliwości taktowania wzmacniają efekt drgań, ponieważ zwiększają prawdopodobieństwo, że jakiekolwiek drgania spowodują utratę klatki. Dlatego im bliżej wartości 60 FPS jest parametr TouchLatency, tym mniejsze jest prawdopodobieństwo wystąpienia nieprawidłowego działania systemu, które powoduje sporadyczne, trudne do odtworzenia zacięcia w większych aplikacjach.
Jitter jest często (ale nie zawsze) niezależny od szybkości zegara, dlatego do diagnozowania jittera używaj testu, który działa przy bardzo niskich szybkościach zegara. Oto powody:
- Nie wszystkie drgania są niezależne od szybkości zegara. Wiele źródeł po prostu zużywa czas procesora.
- Regulator powinien zbliżyć średni czas klatki do terminu przez obniżenie częstotliwości zegara, aby czas poświęcony na wykonywanie zadań niezwiązanych z interfejsem użytkownika mógł spowodować przekroczenie terminu i pominięcie klatki.