Ocena wydajności

Użyj Simpleperf , aby ocenić wydajność urządzenia. Simpleperf to natywne narzędzie do profilowania zarówno aplikacji, jak i natywnych procesów w systemie Android. Użyj narzędzia CPU Profiler , aby w czasie rzeczywistym sprawdzać użycie procesora przez aplikację i aktywność wątków.

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

  • Przewidywalna, wyczuwalna wydajność . Czy interfejs użytkownika (UI) opuszcza klatki lub jest stale renderowany przy 60 klatkach na sekundę? Czy dźwięk jest odtwarzany bez artefaktów i trzasków? Jak długo trwa opóźnienie między dotknięciem ekranu przez użytkownika a pojawieniem się efektu na wyświetlaczu?
  • Czas wymagany do dłuższych operacji (takich jak otwieranie aplikacji).

Pierwszy jest bardziej zauważalny niż drugi. Użytkownicy zazwyczaj zauważają szarpnięcie, ale nie będą w stanie określić czasu uruchamiania aplikacji 500 ms vs 600 ms, chyba że patrzą na dwa urządzenia obok siebie. Opóźnienie dotyku jest natychmiast zauważalne i znacząco wpływa na percepcję urządzenia.

W rezultacie w szybkim urządzeniu potok interfejsu użytkownika jest najważniejszą rzeczą w systemie poza tym, co jest konieczne do utrzymania funkcjonalności potoku interfejsu użytkownika. Oznacza to, że potok interfejsu użytkownika powinien zapobiegać wszelkim innym pracom, które nie są konieczne w przypadku płynnego interfejsu użytkownika. Aby utrzymać płynny interfejs użytkownika, synchronizacja w tle, dostarczanie powiadomień i podobne działania muszą być opóźnione, jeśli można uruchomić pracę interfejsu użytkownika. Dopuszczalne jest wymienianie wydajności dłuższych operacji (środowiska wykonawczego HDR+, uruchamiania aplikacji itp.), aby zachować płynny interfejs użytkownika.

Pojemność a jitter

Rozważając wydajność urządzenia, pojemność i fluktuacje to dwie istotne metryki.

Pojemność

Pojemność to całkowita ilość zasobu, który urządzenie posiada przez pewien czas. Mogą to być zasoby procesora, zasoby GPU, 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 składników i założenie pojedynczej metryki, która określa wydajność (zwłaszcza podczas dostrajania nowego urządzenia, ponieważ obciążenia uruchamiane na tym urządzeniu są prawdopodobnie naprawione).

Wydajność systemu różni się w zależności od zasobów obliczeniowych online. Zmiana częstotliwości procesora/GPU jest podstawowym sposobem zmiany pojemności, ale są też inne, takie jak zmiana liczby rdzeni procesora online. W związku z tym wydajność systemu odpowiada zużyciu energii; zmiana pojemności zawsze skutkuje podobną zmianą zużycia energii.

Wymagana w danym momencie pojemność jest w przeważającej mierze uzależniona od uruchomionej aplikacji. W rezultacie platforma może niewiele zrobić, aby dostosować pojemność wymaganą dla danego obciążenia, a środki do tego ograniczają się do ulepszeń środowiska wykonawczego (frameworka Androida, ART, Bionic, kompilator/sterowniki GPU, jądro).

Drganie

Podczas gdy wymagana pojemność dla obciążenia jest łatwa do zauważenia, jitter jest pojęciem bardziej mglistym. Aby uzyskać dobre wprowadzenie do jittera jako przeszkody w szybkich systemach, zapoznaj się z PRZYPADKIEM BRAKUJĄCEGO 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 jest doskonałym wprowadzeniem do optymalizacji dużych systemów).

Ta strona używa terminu jitter, aby opisać to, co dokument ASCI Q nazywa szumem . Jitter to losowe zachowanie systemu, które zapobiega uruchamianiu zauważalnej pracy. Często jest to praca, którą należy wykonać, ale może nie mieć ścisłych wymagań dotyczących czasu, które powodują, że jest uruchamiana w określonym czasie. Ponieważ jest losowy, niezwykle trudno jest obalić istnienie jittera dla danego obciążenia. Niezwykle trudno jest również udowodnić, że znane źródło jittera było przyczyną konkretnego problemu z wydajnością. Narzędzia najczęściej używane do diagnozowania przyczyn jittera (takie jak śledzenie lub rejestrowanie) mogą wprowadzać własne jitter.

Źródła jittera 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ługotrwałe softirqs
  • Rywalizacja o blokadę (aplikacja, framework, sterownik jądra, blokada bindera, blokada mmap)
  • Rywalizacja o deskryptor plików, w której 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 być opóźniony
  • Przejścia bezczynności procesora
  • Logowanie
  • Opóźnienia we/wy
  • Tworzenie niepotrzebnych procesów (np. transmisje CONNECTIVITY_CHANGE)
  • Przerzucanie pamięci podręcznej stron spowodowane niewystarczającą ilością wolnej pamięci

Wymagana ilość czasu dla danego okresu jittera może, ale nie musi się zmniejszać wraz ze wzrostem pojemności. Na przykład, jeśli sterownik pozostawi wyłączone przerwania podczas oczekiwania na odczyt z magistrali i2c, zajmie to określoną ilość czasu, niezależnie od tego, czy procesor pracuje na częstotliwości 384 MHz czy 2 GHz. Zwiększenie pojemności nie jest wykonalnym rozwiązaniem poprawiającym wydajność, gdy w grę wchodzi jitter. W rezultacie szybsze procesory zwykle nie poprawiają wydajności w sytuacjach z ograniczeniem jittera.

Wreszcie, w przeciwieństwie do pojemności, jitter jest prawie całkowicie domeną dostawcy systemu.

Zużycie pamięci

Zużycie pamięci jest tradycyjnie obwiniane za niską wydajność. Chociaż samo zużycie nie jest problemem z wydajnością, może powodować fluktuacje spowodowane niskim obciążeniem pamięci, restartami usług i czyszczeniem pamięci podręcznej stron. Zmniejszenie zużycia pamięci może zapobiec bezpośrednim przyczynom niskiej wydajności, ale mogą istnieć inne ukierunkowane ulepszenia, które również unikają tych przyczyn (na przykład przypinanie struktury, aby zapobiec jej stronicowaniu, gdy zostanie wkrótce po stronicowana).

Analiza początkowej wydajności urządzenia

Rozpoczęcie od funkcjonalnego, ale słabo działającego systemu i próba naprawienia zachowania systemu poprzez przyjrzenie się indywidualnym przypadkom widocznej dla użytkownika słabej wydajności nie jest dobrą strategią. Ponieważ słaba wydajność zwykle nie jest łatwa do odtworzenia (tj. jitter) lub 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, jednocześnie tracąc systemowe możliwości naprawy wydajności w całym systemie.

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

  1. Uruchom system w interfejsie użytkownika ze wszystkimi uruchomionymi 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 sched_blocked_reason oraz inne punkty śledzenia w potoku wyświetlania, które wskazują, kiedy ramka jest dostarczana do ekranu.
  3. Wykonuj długie ślady całego potoku interfejsu użytkownika (od odbierania danych wejściowych przez IRQ do końcowego skanowania) podczas uruchamiania lekkiego i spójnego obciążenia (np. UiBench lub test kulkowy w TouchLatency) .
  4. Napraw spadki ramek wykryte w lekkim i spójnym obciążeniu.
  5. Powtarzaj kroki 3-4, aż będziesz mógł biegać bez pominiętych klatek przez ponad 20 sekund na raz.
  6. Przejdź do innych widocznych dla użytkownika źródeł szarpnięcia.

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

  • Upewnij się, że jądro ma łatkę sched_blocked_reason tracepoint . Ten punkt śledzenia jest włączony z kategorią śledzenia sched w systrace i udostępnia funkcję odpowiedzialną za uśpienie, gdy ten wątek przechodzi w stan uśpienia bezprzerwowego. Ma to kluczowe znaczenie dla analizy wydajności, ponieważ nieprzerwany sen jest bardzo częstym wskaźnikiem jittera.
  • Upewnij się, że masz wystarczającą ilość śledzenia dla GPU i potoków wyświetlania. W najnowszych SOC firmy 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"
    

    Te zdarzenia pozostają włączone po uruchomieniu systrace, dzięki czemu w śledzeniu można zobaczyć dodatkowe informacje dotyczące potoku wyświetlania (MDSS) w sekcji mdss_fb0 . W przypadku SOC firmy Qualcomm nie zobaczysz żadnych dodatkowych informacji o procesorze GPU w standardowym widoku systrace, ale wyniki są obecne w samym śledzeniu (aby uzyskać szczegółowe informacje, zobacz Omówienie systrace ).

    To, czego oczekujesz od tego rodzaju śledzenia wyświetlania, to pojedyncze zdarzenie, które bezpośrednio wskazuje, że ramka została dostarczona na wyświetlacz. Stamtąd możesz określić, czy pomyślnie osiągnąłeś czas wyświetlania klatek; jeśli zdarzenie X n wystąpi mniej niż 16,7 ms po zdarzeniu X n-1 (przy założeniu wyświetlania 60 Hz), to wiesz, że nie szarpnęłaś. 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 zapewnienia podstawowej funkcjonalności urządzenia. Jednak traktowanie testów porównawczych jako proxy dla postrzeganej wydajności urządzenia nie jest przydatne.

Na podstawie doświadczeń z SOC różnice w wydajności syntetycznego testu porównawczego między SOC nie są skorelowane z podobną różnicą w odczuwalnej wydajności interfejsu użytkownika (liczba utraconych klatek, 99. percentyl czasu wyświetlania klatek itp.). Syntetyczne wskaźniki referencyjne są wskaźnikami odnoszącymi się wyłącznie do zdolności; jitter wpływa na zmierzoną wydajność tych benchmarków tylko poprzez kradzież czasu z masowego działania benchmarku. W rezultacie syntetyczne wyniki testów porównawczych są w większości nieistotne jako metryka wydajności postrzeganej przez użytkownika.

Rozważmy dwa SOC z systemem Benchmark X, które renderują 1000 klatek interfejsu użytkownika i zgłaszają całkowity czas renderowania (niższy wynik jest lepszy).

  • SOC 1 renderuje każdą klatkę Benchmark X w 10 ms i uzyskuje 10 000 punktów.
  • SOC 2 renderuje 99% klatek w ciągu 1 ms, ale 1% klatek w ciągu 100 ms i uzyskuje 19 900 punktów, znacznie lepszy wynik.

Jeśli benchmark wskazuje na 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 niestabilną ramkę co 1,5 sekundy 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 ciężkie, rzadko są przydatne do debugowania sporadycznych problemów z szarpnięciem. Mogą dostarczać wskazówek na temat tego, co system robił w danym momencie, zwłaszcza jeśli szarpnięcie dotyczyło przejścia aplikacji (co jest rejestrowane w raporcie o błędzie). Raporty o błędach mogą również wskazywać, kiedy coś jest ogólnie nie tak z systemem, co może zmniejszyć jego efektywną pojemność (takie jak dławienie termiczne lub fragmentacja pamięci).

Korzystanie z opóźnienia dotykowego

Kilka przykładów złego zachowania pochodzi z TouchLatency, które jest preferowanym okresowym obciążeniem używanym w Pixel i Pixel XL. Jest dostępny w frameworks/base/tests/TouchLatency i ma dwa tryby: opóźnienie dotyku i odbijanie piłki (aby zmienić 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ę od ekranu w nieskończoność, niezależnie od tego, co wprowadzi użytkownik. Zwykle jest to również zdecydowanie najtrudniejszy test do perfekcyjnego uruchomienia, ale im bardziej zbliża się do działania bez żadnych pominiętych klatek, tym lepsze będzie twoje urządzenie. Test odbijającej się kuli jest trudny, ponieważ jest to trywialne, ale doskonale spójne obciążenie, które działa z bardzo niskim zegarem (przy założeniu, że urządzenie ma regulator częstotliwości; jeśli zamiast tego urządzenie działa ze stałymi zegarami, zmniejsz częstotliwość CPU/GPU do minimum podczas wykonywania testu odbijającej się piłki po raz pierwszy). Gdy system się uspokaja, a zegary zbliżają się do stanu bezczynności, wymagany czas procesora/GPU na klatkę wzrasta. Możesz oglądać piłkę i widzieć szarpnięcia, a także w systrace będziesz mógł zobaczyć pominięte klatki.

Ponieważ obciążenie jest tak spójne, można znacznie łatwiej zidentyfikować większość źródeł fluktuacji niż w przypadku większości obciążeń widocznych dla użytkownika, śledząc, co dokładnie działa w systemie podczas każdej pominiętej klatki zamiast potoku interfejsu użytkownika. Niższe zegary wzmacniają efekty jittera, zwiększając prawdopodobieństwo, że jakikolwiek jitter spowoduje utratę klatki. W rezultacie im bliżej TouchLatency jest 60FPS, 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 (ale nie zawsze) niezmienny od prędkości zegara, użyj testu, który działa przy bardzo niskich zegarach, aby zdiagnozować jitter z następujących powodów:

  • Nie wszystkie fluktuacje są niezmienne od szybkości zegara; wiele źródeł po prostu zużywa czas procesora.
  • Zarządca powinien skrócić średni czas wyświetlania klatek do ostatecznego terminu, zmniejszając taktowanie, aby czas spędzony na wykonywaniu zadań niezwiązanych z interfejsem użytkownika mógł zepchnąć go ponad granicę i porzucić ramkę.