Ocena wydajności

Użyj Simpleperf, aby ocenić wydajność urządzenia. Simpleperf to natywne narzędzie do profilowania zarówno aplikacji, jak i procesów natywnych na Androidzie. Użyj CPU Profiler, aby sprawdzić wykorzystanie procesora aplikacji i aktywność wątków w czasie rzeczywistym.

Istnieją dwa widoczne dla użytkownika wskaźniki wydajności:

  • Przewidywalna, odczuwalna wydajność . Czy interfejs użytkownika (UI) gubi klatki lub renderuje stale z szybkością 60 klatek na sekundę? Czy dźwięk jest odtwarzany bez artefaktów i trzasków? Jak długie jest opóźnienie pomiędzy dotknięciem ekranu przez użytkownika a pojawieniem się efektu na wyświetlaczu?
  • Czas potrzebny na dłuższe operacje (takie jak otwieranie aplikacji).

To pierwsze jest bardziej zauważalne niż drugie. Użytkownicy zazwyczaj zauważają Jank, ale nie będą w stanie określić czasu uruchamiania aplikacji 500 ms vs 600 ms, chyba że spojrzą na dwa urządzenia obok siebie. Opóźnienie dotyku jest natychmiast zauważalne i znacząco wpływa na postrzeganie urządzenia.

W rezultacie w szybkim urządzeniu potok interfejsu użytkownika jest najważniejszą rzeczą w systemie, inną niż to, co jest konieczne do utrzymania funkcjonalności potoku interfejsu użytkownika. Oznacza to, że potok interfejsu użytkownika powinien wywłaszczać wszelkie inne prace, które nie są konieczne w przypadku płynnego interfejsu użytkownika. Aby zachować płynny interfejs użytkownika, synchronizacja w tle, dostarczanie powiadomień i podobne prace muszą zostać opóźnione, jeśli można uruchomić pracę interfejsu użytkownika. Dopuszczalne jest zastąpienie wydajności dłuższych operacji (czas działania HDR+, uruchamianie aplikacji itp.) na rzecz płynnego interfejsu użytkownika.

Pojemność a jitter

Rozważając wydajność urządzenia, pojemność i wahania to dwa znaczące wskaźniki.

Pojemność

Pojemność to całkowita ilość jakiegoś zasobu, którą urządzenie posiada w określonym czasie. Mogą to być zasoby procesora, zasoby procesora graficznego, zasoby we/wy, zasoby sieciowe, przepustowość pamięci lub dowolna podobna metryka. Podczas badania wydajności całego systemu przydatne może być wyodrębnienie poszczególnych komponentów i przyjęcie jednej metryki określającej wydajność (szczególnie podczas dostrajania nowego urządzenia, ponieważ obciążenia uruchamiane na tym urządzeniu są prawdopodobnie stałe).

Wydajność systemu różni się w zależności od zasobów obliczeniowych dostępnych w Internecie. Zmiana częstotliwości procesora/GPU jest głównym sposobem zmiany wydajności, ale są też inne sposoby, takie jak zmiana liczby rdzeni procesora online. Odpowiednio, wydajność systemu odpowiada zużyciu energii; zmiana wydajności zawsze skutkuje podobną zmianą w zużyciu energii.

Wydajność wymagana w danym momencie jest w przeważającej mierze zależna od uruchomionej aplikacji. W rezultacie platforma może niewiele zrobić, aby dostosować pojemność wymaganą do danego obciążenia, a środki w tym celu ograniczają się do ulepszeń środowiska wykonawczego (framework Android, ART, Bionic, kompilator/sterowniki GPU, jądro).

Drganie

Chociaż wymaganą pojemność dla danego obciążenia łatwo jest dostrzec, drgania są pojęciem bardziej mglistym. Dobre wprowadzenie do jittera jako przeszkody w szybkich systemach można znaleźć w PRZYPADKU BRAKU WYDAJNOŚCI SUPERKOMPUTERA: OSIĄGNIĘCIE OPTYMALNEJ WYDAJNOŚCI NA 8192 PROCESORACH ASCl Q. (Jest to badanie, dlaczego superkomputer ASCI Q nie osiągnął oczekiwanej wydajności i stanowi doskonałe wprowadzenie do optymalizacji dużych systemów.)

Na tej stronie termin jitter opisuje to, co w artykule ASCI Q nazywa się szumem . Jitter to losowe zachowanie systemu, które uniemożliwia wykonanie zauważalnej pracy. Często jest to praca, którą należy wykonać, ale może nie mieć ścisłych wymagań czasowych, które powodują, że jest ona uruchamiana w określonym czasie. Ponieważ jest to losowe, niezwykle trudno jest obalić istnienie jittera dla danego obciążenia. Niezwykle trudno jest również udowodnić, że znane źródło drgań było przyczyną konkretnego problemu z wydajnością. Narzędzia najczęściej używane do diagnozowania przyczyn fluktuacji (takie jak śledzenie lub rejestrowanie) mogą wprowadzać własne fluktuacje.

Źródła drgań występujące w rzeczywistych implementacjach Androida obejmują:

  • Opóźnienie harmonogramu
  • Obsługa przerwań
  • Kod sterownika działa zbyt długo z wyłączonym wywłaszczaniem lub przerwaniami
  • Długo działające softirqs
  • Zablokuj rywalizację (aplikacja, framework, sterownik jądra, blokada segregatora, blokada mmap)
  • Konflikt o deskryptor 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 użytkownika w kolejkach roboczych, gdzie może to być opóźnione
  • Przejścia bezczynności procesora
  • Logowanie
  • Opóźnienia we/wy
  • Niepotrzebne tworzenie procesów (np. transmisje CONNECTIVITY_CHANGE)
  • Błąd pamięci podręcznej strony spowodowany niewystarczającą ilością wolnej pamięci

Wymagana ilość czasu dla danego okresu fluktuacji może, ale nie musi, zmniejszać się wraz ze wzrostem pojemności. Na przykład, jeśli sterownik pozostawi wyłączone przerwania podczas oczekiwania na odczyt z magistrali i2c, zajmie to stałą ilość czasu, niezależnie od tego, czy procesor ma częstotliwość 384 MHz, czy 2 GHz. Zwiększanie pojemności nie jest możliwym rozwiązaniem w celu poprawy wydajności, gdy występuje jitter. W rezultacie szybsze procesory zwykle nie poprawiają wydajności w sytuacjach ograniczonych jitterem.

Wreszcie, w przeciwieństwie do wydajności, fluktuacja leży prawie wyłącznie w gestii dostawcy systemu.

Zużycie pamięci

Zużycie pamięci jest tradycyjnie obwiniane za słabą wydajność. Chociaż zużycie samo w sobie nie jest problemem związanym z wydajnością, może powodować drgania w wyniku narzutu zmniejszającego pamięć, ponownego uruchamiania usług i niszczenia pamięci podręcznej stron. Zmniejszenie zużycia pamięci pozwala uniknąć bezpośrednich przyczyn słabej wydajności, ale mogą istnieć inne ukierunkowane ulepszenia, które również pozwolą uniknąć tych przyczyn (na przykład przypinanie struktury, aby zapobiec jej stronicowaniu, gdy zostanie stronicowane wkrótce potem).

Analizowanie początkowej wydajności urządzenia

Rozpoczęcie od funkcjonalnego, ale słabo działającego systemu i próba naprawienia jego zachowania poprzez przyjrzenie się indywidualnym przypadkom widocznej przez użytkownika słabej wydajności nie jest rozsądną strategią. Ponieważ słabej wydajności zwykle nie da się łatwo odtworzyć (tzn. drgań) lub jest to problem z aplikacją, zbyt wiele zmiennych w całym systemie uniemożliwia skuteczność tej strategii. W rezultacie bardzo łatwo jest błędnie zidentyfikować przyczyny i wprowadzić drobne ulepszenia, tracąc przy tym systemowe możliwości naprawy wydajności w całym systemie.

Zamiast tego przy wprowadzaniu nowego urządzenia zastosuj następujące ogólne podejście:

  1. Uruchom system do interfejsu użytkownika z uruchomionymi wszystkimi sterownikami i niektórymi podstawowymi ustawieniami regulatora częstotliwości (jeśli zmienisz ustawienia regulatora częstotliwości, powtórz wszystkie poniższe kroki).
  2. Upewnij się, że jądro obsługuje punkt śledzenia sched_blocked_reason , a także inne punkty śledzenia w potoku wyświetlania, które wskazują, kiedy ramka jest dostarczana na wyświetlacz.
  3. Wykonuj długie ślady całego potoku interfejsu użytkownika (od otrzymania danych wejściowych przez przerwanie IRQ do końcowego skanowania), uruchamiając lekkie i spójne obciążenie (np. UiBench lub test kulkowy w TouchLatency) .
  4. Napraw spadki klatek wykryte przy lekkim i stałym obciążeniu.
  5. Powtarzaj kroki 3-4, aż będziesz mógł biegać z zerową liczbą porzuconych klatek przez ponad 20 sekund na raz.
  6. Przejdź do innych widocznych dla użytkownika źródeł jank.

Inne proste rzeczy, które możesz zrobić na początku konfiguracji urządzenia, to:

  • Upewnij się, że twoje jądro ma łatkę punktu śledzenia sched_blocked_reason . Ten punkt śledzenia jest włączany w kategorii śledzenia sched w systrace i zapewnia funkcję odpowiedzialną za uśpienie, gdy wątek przejdzie w stan uśpienia nieprzerwanego. Ma to kluczowe znaczenie dla analizy wydajności, ponieważ nieprzerwany sen jest bardzo częstym wskaźnikiem drgań.
  • Upewnij się, że masz wystarczające śledzenie dla procesora graficznego i potoków wyświetlania. W najnowszych SOC Qualcomm punkty śledzenia są włączane przy użyciu:
  • adb shell "echo 1 > /d/tracing/events/kgsl/enable"
    adb shell "echo 1 > /d/tracing/events/mdss/enable"
    

    Zdarzenia te pozostają włączone po uruchomieniu systrace, dzięki czemu w sekcji mdss_fb0 można zobaczyć dodatkowe informacje dotyczące potoku wyświetlania (MDSS). W przypadku Qualcomm SOC nie zobaczysz żadnych dodatkowych informacji o GPU w standardowym widoku systrace, ale wyniki są obecne w samym śladzie (więcej szczegółów znajdziesz w Omówienie systrace ).

    W przypadku tego rodzaju śledzenia wyświetlania wymagane jest pojedyncze zdarzenie, które bezpośrednio wskazuje, że ramka została dostarczona na wyświetlacz. Na tej podstawie możesz sprawdzić, czy udało Ci się osiągnąć wymagany czas klatek; jeśli zdarzenie X n nastąpi w czasie krótszym niż 16,7 ms po zdarzeniu X n-1 (zakładając, że wyświetlacz ma częstotliwość 60 Hz), to wiesz, że nie szarpnąłeś. Jeśli Twój SOC nie zapewnia takich sygnałów, skontaktuj się ze swoim dostawcą, aby je uzyskać. Debugowanie jittera jest niezwykle trudne bez ostatecznego sygnału zakończenia ramki.

Korzystanie z syntetycznych benchmarków

Syntetyczne testy porównawcze są przydatne do sprawdzenia, czy urządzenie spełnia podstawową funkcjonalność. Jednak traktowanie testów porównawczych jako wskaźnika postrzeganej wydajności urządzenia nie jest przydatne.

Z doświadczeń z SOC wynika, że ​​różnice w wydajności syntetycznego testu porównawczego między SOC nie są skorelowane z podobną różnicą w zauważalnej wydajności interfejsu użytkownika (liczba utraconych klatek, czas wyświetlania klatek na poziomie 99. percentyla itp.). Syntetyczne wskaźniki referencyjne to wskaźniki dotyczące wyłącznie zdolności; Jitter wpływa na zmierzoną wydajność tych testów porównawczych jedynie poprzez kradzież czasu z masowego działania testu porównawczego. W rezultacie syntetyczne wyniki testów porównawczych są w większości nieistotne jako miernik wydajności postrzeganej przez użytkownika.

Rozważmy dwa SOC z uruchomionym programem Benchmark X, który renderuje 1000 klatek interfejsu użytkownika i raportuje całkowity czas renderowania (im niższy wynik, tym lepszy).

  • SOC 1 renderuje każdą klatkę Benchmark X w 10 ms i zdobywa 10 000 punktów.
  • SOC 2 renderuje 99% klatek w 1 ms, ale 1% klatek w 100 ms i osiąga 19 900, co jest znacznie lepszym wynikiem.

Jeśli test porównawczy wskazuje rzeczywistą wydajność interfejsu użytkownika, SOC 2 byłby bezużyteczny. Zakładając częstotliwość odświeżania 60 Hz, SOC 2 miałby nierówną klatkę co 1,5 s działania. Tymczasem SOC 1 (wolniejszy SOC według Benchmark X) byłby idealnie płynny.

Korzystanie z raportów o błędach

Raporty o błędach są czasami przydatne do analizy wydajności, ale ponieważ są tak ważne, rzadko są przydatne do debugowania sporadycznych problemów z Jankiem. Mogą dostarczyć wskazówek na temat tego, co system robił w danym momencie, szczególnie jeśli szarpanie miało miejsce w związku z przejściem aplikacji (co jest rejestrowane w raporcie o błędzie). Raporty o błędach mogą również wskazywać, kiedy z systemem dzieje się coś ogólniejszego, co może zmniejszyć jego efektywną pojemność (np. dławienie termiczne lub fragmentacja pamięci).

Korzystanie z opóźnienia dotykowego

Kilka przykładów złego zachowania pochodzi z funkcji TouchLatency, która jest preferowanym okresowym obciążeniem używanym w telefonach Pixel i Pixel XL. Jest dostępny pod frameworks/base/tests/TouchLatency i ma dwa tryby: opóźnienie dotyku i odbijająca się piłka (aby przełączyć tryby, kliknij przycisk w prawym górnym rogu).

Test odbijającej się piłki jest dokładnie tak prosty, jak się wydaje: piłka odbija się po ekranie w nieskończoność, niezależnie od działań użytkownika. Zwykle jest to zdecydowanie najtrudniejszy test na idealne działanie, ale im bliżej będzie działania bez utraty klatek, tym lepsze będzie Twoje urządzenie. Test odbijającej się piłki jest trudny, ponieważ jest to trywialne, ale doskonale spójne obciążenie, które działa przy bardzo niskim zegarze (zakłada się, że urządzenie ma regulator częstotliwości; jeśli zamiast tego urządzenie działa ze stałymi zegarami, obniż częstotliwość procesora/GPU do niemal minimalnego przy pierwszym uruchomieniu testu odbijającej się piłki). W miarę jak system się wyłącza i zegary zbliżają się do stanu bezczynności, wymagany czas procesora/GPU na klatkę wzrasta. Możesz oglądać piłkę i widzieć, co się dzieje, a także będziesz mógł zobaczyć utracone klatki w systrace.

Ponieważ obciążenie jest tak spójne, większość źródeł drgań można znacznie łatwiej zidentyfikować niż w przypadku większości obciążeń widocznych dla użytkownika, śledząc, co dokładnie dzieje się w systemie podczas każdej pominiętej klatki, zamiast potoku interfejsu użytkownika. Niższe zegary wzmacniają skutki jittera, zwiększając prawdopodobieństwo, że jakikolwiek jitter spowoduje utratę klatek. W rezultacie im bliżej 60 FPS jest TouchLatency, tym mniej prawdopodobne jest, że będziesz mieć złe zachowania systemu, które powodują sporadyczne, trudne do odtworzenia szarpnięcia w większych aplikacjach.

Ponieważ jitter jest często (choć nie zawsze) niezależny od szybkości zegara, należy zastosować test uruchamiany przy bardzo niskich częstotliwościach, aby zdiagnozować jitter z następujących powodów:

  • Nie każdy jitter jest niezależny od szybkości zegara; wiele źródeł po prostu zużywa czas procesora.
  • Gubernator powinien uzyskać średni czas trwania klatki blisko ostatecznego terminu, zmniejszając taktowanie, aby czas spędzony na wykonywaniu zadań innych niż interfejs użytkownika mógł spowodować porzucenie klatki.