Android 8.0 zawiera testy wydajności spoiwa i hwbindera pod kątem przepustowości i opóźnień. Chociaż istnieje wiele scenariuszy wykrywania zauważalnych problemów z wydajnością, uruchamianie takich scenariuszy może być czasochłonne, a wyniki często są niedostępne do czasu integracji systemu. Korzystanie z dostarczonych testów wydajności ułatwia testowanie podczas programowania, wykrywa poważne problemy wcześniej i poprawia komfort użytkownika.
Testy wydajności obejmują następujące cztery kategorie:
- przepustowość segregatora (dostępna w
system/libhwbinder/vts/performance/Benchmark_binder.cpp
) - opóźnienie segregatora (dostępne w
frameworks/native/libs/binder/tests/schd-dbg.cpp
) - przepustowość hwbindera (dostępna w
system/libhwbinder/vts/performance/Benchmark.cpp
) - opóźnienie hwbindera (dostępne w
system/libhwbinder/vts/performance/Latency.cpp
)
O spoiwie i hwbinderze
Binder i hwbinder to infrastruktury komunikacji międzyprocesowej (IPC) systemu Android, które korzystają z tego samego sterownika dla systemu Linux, ale mają następujące różnice jakościowe:
Aspekt | spoiwo | hwbinder |
---|---|---|
Zamiar | Zapewnij schemat IPC ogólnego przeznaczenia dla frameworka | Komunikuj się ze sprzętem |
Nieruchomość | Zoptymalizowany pod kątem użycia platformy Android | Minimalne obciążenie i niskie opóźnienia |
Zmień zasady planowania dla pierwszego/tła | Tak | NIE |
Argumenty przemijają | Wykorzystuje serializację obsługiwaną przez obiekt Parcel | Używa buforów rozproszenia i pozwala uniknąć narzutu związanego z kopiowaniem danych wymaganych do serializacji Parcel |
Dziedziczenie priorytetowe | NIE | Tak |
Procesy wiążące i hwbinderowe
Wizualizator systrace wyświetla transakcje w następujący sposób:
W powyższym przykładzie:
- Cztery (4) procesy schd-dbg są procesami klienckimi.
- Cztery (4) procesy bindera są procesami serwera (nazwa zaczyna się od Binder i kończy numerem sekwencyjnym).
- Proces klienta jest zawsze powiązany z procesem serwera, który jest dedykowany jego klientowi.
- Wszystkie pary procesów klient-serwer są zaplanowane niezależnie przez jądro i jednocześnie.
W CPU 1 jądro systemu operacyjnego uruchamia klienta w celu wysłania żądania. Następnie, jeśli to możliwe, używa tego samego procesora, aby obudzić proces serwera, obsłużyć żądanie i ponownie przełączyć kontekst po zakończeniu żądania.
Przepustowość a opóźnienie
W idealnej transakcji, w której proces klienta i serwera przełączają się płynnie, testy przepustowości i opóźnień nie dają zasadniczo różnych komunikatów. Jednakże, gdy jądro systemu operacyjnego obsługuje żądanie przerwania (IRQ) ze sprzętu, czeka na blokady lub po prostu decyduje się nie natychmiastowo obsługiwać komunikat, może powstać bańka opóźnienia.
Test przepustowości generuje dużą liczbę transakcji o różnych rozmiarach ładunku, zapewniając dobre oszacowanie zwykłego czasu transakcji (w najlepszych scenariuszach) i maksymalnej przepustowości, jaką może osiągnąć segregator.
Natomiast test opóźnienia nie wykonuje żadnych działań na ładunku, aby zminimalizować zwykły czas transakcji. Możemy wykorzystać czas transakcji do oszacowania narzutu związanego z segregatorem, stworzyć statystyki dla najgorszego przypadku i obliczyć współczynnik transakcji, których opóźnienie przekracza określony termin.
Obsługuj inwersje priorytetów
Odwrócenie priorytetu ma miejsce, gdy wątek o wyższym priorytecie logicznie czeka na wątek o niższym priorytecie. W aplikacjach czasu rzeczywistego (RT) występuje problem inwersji priorytetów:
Podczas korzystania z planowania w systemie Linux Completely Fair Scheduler (CFS) wątek zawsze ma szansę na uruchomienie, nawet jeśli inne wątki mają wyższy priorytet. W rezultacie aplikacje korzystające z harmonogramu CFS traktują inwersję priorytetów zgodnie z oczekiwaniami, a nie jako problem. W przypadkach, gdy środowisko Androida wymaga planowania RT, aby zagwarantować przywilej wątków o wysokim priorytecie, należy rozwiązać problem odwrócenia priorytetów.
Przykładowe odwrócenie priorytetów podczas transakcji segregatora (wątek RT jest logicznie blokowany przez inne wątki CFS podczas oczekiwania na obsługę wątku segregatora):
Aby uniknąć blokad, możesz użyć dziedziczenia priorytetów, aby tymczasowo eskalować wątek Binder do wątku RT, gdy obsługuje on żądanie od klienta RT. Należy pamiętać, że planowanie czasu rzeczywistego ma ograniczone zasoby i należy z niego korzystać ostrożnie. W systemie z n procesorami maksymalna liczba bieżących wątków RT również wynosi n ; dodatkowe wątki RT mogą wymagać poczekania (a tym samym przekroczenia terminów), jeśli wszystkie procesory zostaną zajęte przez inne wątki RT.
Aby rozwiązać wszystkie możliwe inwersje priorytetów, możesz użyć dziedziczenia priorytetów zarówno dla bindera, jak i hwbindera. Jednakże, ponieważ segregator jest szeroko stosowany w całym systemie, włączenie dziedziczenia priorytetów dla transakcji segregatorów może spamować system większą liczbą wątków RT, niż jest w stanie obsłużyć.
Uruchom testy przepustowości
Test przepustowości jest uruchamiany względem przepustowości transakcji binder/hwbinder. W systemie, który nie jest przeciążony, bąbelki opóźnień są rzadkie i ich wpływ można wyeliminować, o ile liczba iteracji jest odpowiednio duża.
- Test przepustowości segregatora znajduje się w
system/libhwbinder/vts/performance/Benchmark_binder.cpp
. - Test przepustowości hwbindera znajduje się w
system/libhwbinder/vts/performance/Benchmark.cpp
.
Wyniki testu
Przykładowe wyniki testu przepustowości dla transakcji wykorzystujących różne rozmiary ładunku:
Benchmark Time CPU Iterations --------------------------------------------------------------------- BM_sendVec_binderize/4 70302 ns 32820 ns 21054 BM_sendVec_binderize/8 69974 ns 32700 ns 21296 BM_sendVec_binderize/16 70079 ns 32750 ns 21365 BM_sendVec_binderize/32 69907 ns 32686 ns 21310 BM_sendVec_binderize/64 70338 ns 32810 ns 21398 BM_sendVec_binderize/128 70012 ns 32768 ns 21377 BM_sendVec_binderize/256 69836 ns 32740 ns 21329 BM_sendVec_binderize/512 69986 ns 32830 ns 21296 BM_sendVec_binderize/1024 69714 ns 32757 ns 21319 BM_sendVec_binderize/2k 75002 ns 34520 ns 20305 BM_sendVec_binderize/4k 81955 ns 39116 ns 17895 BM_sendVec_binderize/8k 95316 ns 45710 ns 15350 BM_sendVec_binderize/16k 112751 ns 54417 ns 12679 BM_sendVec_binderize/32k 146642 ns 71339 ns 9901 BM_sendVec_binderize/64k 214796 ns 104665 ns 6495
- Czas wskazuje opóźnienie podróży w obie strony mierzone w czasie rzeczywistym.
- Procesor wskazuje skumulowany czas, w którym zaplanowano test procesorów.
- Iteracje wskazują, ile razy została wykonana funkcja testowa.
Na przykład dla ładunku 8-bajtowego:
BM_sendVec_binderize/8 69974 ns 32700 ns 21296
…maksymalną przepustowość, jaką może osiągnąć segregator, oblicza się jako:
MAKS. przepustowość przy 8-bajtowym ładunku = (8 * 21296)/69974 ~= 2,423 b/ns ~= 2,268 Gb/s
Opcje testowe
Aby uzyskać wyniki w formacie .json, uruchom test z argumentem --benchmark_format=json
:
libhwbinder_benchmark --benchmark_format=json
{
"context": {
"date": "2017-05-17 08:32:47",
"num_cpus": 4,
"mhz_per_cpu": 19,
"cpu_scaling_enabled": true,
"library_build_type": "release"
},
"benchmarks": [
{
"name": "BM_sendVec_binderize/4",
"iterations": 32342,
"real_time": 47809,
"cpu_time": 21906,
"time_unit": "ns"
},
….
}
Uruchom testy opóźnień
Test opóźnienia mierzy czas potrzebny klientowi na rozpoczęcie inicjowania transakcji, przejście do procesu serwera w celu obsługi i otrzymanie wyniku. Test szuka również znanych nieprawidłowych zachowań programu planującego, które mogą negatywnie wpłynąć na opóźnienia transakcji, na przykład programu planującego, który nie obsługuje dziedziczenia priorytetów ani nie honoruje flagi synchronizacji.
- Test opóźnienia segregatora znajduje się w
frameworks/native/libs/binder/tests/schd-dbg.cpp
. - Test opóźnienia hwbindera znajduje się w
system/libhwbinder/vts/performance/Latency.cpp
.
Wyniki testu
Wyniki (w formacie .json) przedstawiają statystyki dotyczące średniego/najlepszego/najgorszego opóźnienia oraz liczby niedotrzymanych terminów.
Opcje testowe
Testy opóźnień obejmują następujące opcje:
Komenda | Opis |
---|---|
-i value | Określ liczbę iteracji. |
-pair value | Określ liczbę par procesów. |
-deadline_us 2500 | Określ w nas termin. |
-v | Uzyskaj szczegółowe dane wyjściowe (debugowania). |
-trace | Zatrzymaj śledzenie po osiągnięciu ostatecznego terminu. |
W poniższych sekcjach szczegółowo opisano każdą opcję, opisano użycie i przedstawiono przykładowe wyniki.
Określ iteracje
Przykład z dużą liczbą iteracji i wyłączonymi szczegółowymi wynikami:
libhwbinder_latency -i 5000 -pair 3
{
"cfg":{"pair":3,"iterations":5000,"deadline_us":2500},
"P0":{"SYNC":"GOOD","S":9352,"I":10000,"R":0.9352,
"other_ms":{ "avg":0.2 , "wst":2.8 , "bst":0.053, "miss":2, "meetR":0.9996},
"fifo_ms": { "avg":0.16, "wst":1.5 , "bst":0.067, "miss":0, "meetR":1}
},
"P1":{"SYNC":"GOOD","S":9334,"I":10000,"R":0.9334,
"other_ms":{ "avg":0.19, "wst":2.9 , "bst":0.055, "miss":2, "meetR":0.9996},
"fifo_ms": { "avg":0.16, "wst":3.1 , "bst":0.066, "miss":1, "meetR":0.9998}
},
"P2":{"SYNC":"GOOD","S":9369,"I":10000,"R":0.9369,
"other_ms":{ "avg":0.19, "wst":4.8 , "bst":0.055, "miss":6, "meetR":0.9988},
"fifo_ms": { "avg":0.15, "wst":1.8 , "bst":0.067, "miss":0, "meetR":1}
},
"inheritance": "PASS"
}
Wyniki testu pokazują, co następuje:
-
"pair":3
- Tworzy jedną parę klient-serwer.
-
"iterations": 5000
- Obejmuje 5000 iteracji.
-
"deadline_us":2500
- Termin ostateczny to 2500 us (2,5 ms); oczekuje się, że większość transakcji osiągnie tę wartość.
-
"I": 10000
- Pojedyncza iteracja testu obejmuje dwie (2) transakcje:
- Jedna transakcja o normalnym priorytecie (
CFS other
) - Jedna transakcja według priorytetu czasu rzeczywistego (
RT-fifo
)
- Jedna transakcja o normalnym priorytecie (
-
"S": 9352
- 9352 transakcji jest synchronizowanych w tym samym procesorze.
-
"R": 0.9352
- Wskazuje stopień synchronizacji klienta i serwera w tym samym procesorze.
-
"other_ms":{ "avg":0.2 , "wst":2.8 , "bst":0.053, "miss":2, "meetR":0.9996}
- Średni (
avg
), najgorszy (wst
) i najlepszy (bst
) przypadek wszystkich transakcji wydanych przez osobę wywołującą o normalnym priorytecie. Dwie transakcjemiss
terminu, przez co współczynnik spełnienia (meetR
) wynosi 0,9996. -
"fifo_ms": { "avg":0.16, "wst":1.5 , "bst":0.067, "miss":0, "meetR":1}
- Podobny do
other_ms
, ale dla transakcji wystawianych przez klienta z priorytetemrt_fifo
. Jest prawdopodobne (ale nie wymagane), żefifo_ms
ma lepszy wynik niżother_ms
, z niższymi wartościamiavg
iwst
oraz wyższymmeetR
(różnica może być jeszcze bardziej znacząca przy obciążeniu w tle).
Uwaga: obciążenie w tle może mieć wpływ na wynik przepustowości i krotkę other_ms
w teście opóźnienia. Tylko fifo_ms
może pokazać podobne wyniki, o ile ładowanie w tle ma niższy priorytet niż RT-fifo
.
Określ wartości par
Każdy proces klienta jest sparowany z procesem serwera dedykowanym dla klienta, a każda para może być planowana niezależnie dla dowolnego procesora. Jednak migracja procesora nie powinna mieć miejsca podczas transakcji, jeśli flaga SYNC ma honor
.
Upewnij się, że system nie jest przeciążony! Chociaż w przeciążonym systemie oczekuje się dużych opóźnień, wyniki testów dla przeciążonego systemu nie dostarczają użytecznych informacji. Aby przetestować system przy wyższym ciśnieniu, użyj -pair #cpu-1
(lub -pair #cpu
zachowując ostrożność). Testowanie przy użyciu -pair n
z n > #cpu
przeciąża system i generuje bezużyteczne informacje.
Określ wartości ostatecznych terminów
Po szeroko zakrojonych testach scenariuszy z użytkownikami (przeprowadzeniu testu opóźnienia na zakwalifikowanym produkcie) ustaliliśmy, że ostatecznym terminem do dotrzymania jest 2,5 ms. W przypadku nowych aplikacji o wyższych wymaganiach (np. 1000 zdjęć/sekundę) ta wartość terminu ulegnie zmianie.
Określ szczegółowe dane wyjściowe
Użycie opcji -v
powoduje wyświetlenie pełnych wyników. Przykład:
libhwbinder_latency -i 1 -v
-------------------------------------------------- service pid: 8674 tid: 8674 cpu: 1 SCHED_OTHER 0-------------------------------------------------- main pid: 8673 tid: 8673 cpu: 1 -------------------------------------------------- client pid: 8677 tid: 8677 cpu: 0 SCHED_OTHER 0-------------------------------------------------- fifo-caller pid: 8677 tid: 8678 cpu: 0 SCHED_FIFO 99 -------------------------------------------------- hwbinder pid: 8674 tid: 8676 cpu: 0 ??? 99-------------------------------------------------- other-caller pid: 8677 tid: 8677 cpu: 0 SCHED_OTHER 0 -------------------------------------------------- hwbinder pid: 8674 tid: 8676 cpu: 0 SCHED_OTHER 0
- Wątek usługi jest tworzony z priorytetem
SCHED_OTHER
i uruchamiany wCPU:1
zpid 8674
. - Pierwsza transakcja jest następnie rozpoczynana przez
fifo-caller
. Aby obsłużyć tę transakcję, hwbinder podnosi priorytet serwera (pid: 8674 tid: 8676
) do 99, a także oznacza go klasą planowania przejściowego (drukowaną jako???
). Następnie program planujący umieszcza proces serwera wCPU:0
aby mógł zostać uruchomiony, i synchronizuje go z tym samym procesorem, co jego klient. - Drugi obiekt wywołujący transakcję ma priorytet
SCHED_OTHER
. Serwer sam obniża wersję i obsługuje obiekt wywołujący z priorytetemSCHED_OTHER
.
Użyj śledzenia do debugowania
Można określić opcję -trace
, aby debugować problemy z opóźnieniami. Gdy jest używany, test opóźnienia zatrzymuje zapis dziennika śledzenia w momencie wykrycia złego opóźnienia. Przykład:
atrace --async_start -b 8000 -c sched idle workq binder_driver sync freq
libhwbinder_latency -deadline_us 50000 -trace -i 50000 -pair 3
deadline triggered: halt ∓ stop trace log:/sys/kernel/debug/tracing/trace
Następujące komponenty mogą mieć wpływ na opóźnienia:
- Tryb kompilacji Androida . Tryb Eng jest zwykle wolniejszy niż tryb debugowania użytkownika.
- Ramy . W jaki sposób usługa frameworka używa
ioctl
do konfiguracji w segregatorze? - Sterownik segregatora . Czy sterownik obsługuje precyzyjne blokowanie? Czy zawiera wszystkie poprawki poprawiające wydajność?
- Wersja jądra . Im lepsze możliwości działania w czasie rzeczywistym posiada jądro, tym lepsze wyniki.
- Konfiguracja jądra . Czy konfiguracja jądra zawiera konfiguracje
DEBUG
, takie jakDEBUG_PREEMPT
iDEBUG_SPIN_LOCK
? - Harmonogram jądra . Czy jądro ma harmonogram uwzględniający energię (EAS) lub harmonogram heterogenicznego przetwarzania wieloprocesowego (HMP)? Czy jakieś sterowniki jądra (sterownik
cpu-freq
, sterownikcpu-idle
,cpu-hotplug
itp.) wpływają na harmonogram?