Z tego artykułu dowiesz się, w jaki sposób system audio Androida stara się unikać odwrócenie priorytetów, i wyróżniamy techniki, które również możesz wykorzystać.
Techniki te mogą być przydatne dla programistów o wysokiej wydajności aplikacji audio, producentów OEM i dostawców układów SOC, którzy implementują ścieżki audio HAL. Pamiętaj, że wdrażanie tych technik nie jest w celu uniknięcia usterek i innych awarii, zwłaszcza w przypadku, poza kontekstem audio. Uzyskane wyniki mogą się różnić, dlatego należy przeprowadzić własną analizę jego weryfikacji i testowania.
Tło
serwer audio Android AudioFlinger i ścieżka audio/nagrywanie audio. wdrożenie klienta zmienia architekturę, aby zmniejszyć czas oczekiwania. Zaczęliśmy z niej korzystać w Androidzie 4.1 i kontynuowaliśmy kolejne usprawnienia. w wersjach 4.2, 4.3, 4.4 i 5.0.
Aby osiągnąć krótszy czas oczekiwania, konieczne było wprowadzenie wielu zmian w całym systemie. Jedna ważna zmiana polega na przypisaniu zasobów procesora do zasobów o kluczowym znaczeniu w wątkach z bardziej przewidywalną zasadą planowania. Niezawodne planowanie umożliwia zmniejszenie rozmiaru i liczby buforów dźwięku przy jednoczesnym zachowaniu i unikaniu przestojów.
Odwrócenie priorytetów
Odwrócenie priorytetów to klasyczny tryb awarii systemów działających w czasie rzeczywistym, w którym zadanie o wyższym priorytecie jest blokowane na nieograniczony czas oczekiwania w przypadku zadania o niższym priorytecie, które pozwala zwolnić zasób, taki jak (współdzielony państwa chronione przez) mutex.
W systemie audio odwrócenie priorytetów zwykle ma postać zakłócenie (kliknij, wyskocz, zrzuć) powtarzający się dźwięk podczas buforowania cyklicznego lub opóźnienia w odpowiedzi na polecenie.
Częstym obejściem odwrócenia priorytetu jest zwiększenie rozmiaru bufora audio. Ta metoda wydłuża jednak czas oczekiwania i tylko ukrywa problem. zamiast rozwiązywać zagadkę. lepiej poznać priorytety kampanii i im zapobiegać, jak widać poniżej.
W implementacji audio w Androidzie odwrócenie priorytetów jest najbardziej mogą wystąpić w tych miejscach. Dlatego warto skupić się na tym obszarze:
- między zwykłym mikserem a wątkiem szybkiego miksera w AudioFlinger
- między wątkiem wywołania zwrotnego aplikacji, który zapewnia szybką funkcję AudioTrack, szybki mikser (obie mają wyższy priorytet, ale nieco różne priorytety)
- między wątkiem wywołania zwrotnego aplikacji, który zapewnia szybki nagrywanie dźwięku wątek z szybkim przechwytywaniem (podobny do poprzedniego)
- w ramach implementacji sprzętowej warstwy abstrakcji (HAL) audio, np. w celu usunięcia połączeń telefonicznych lub echa
- w ramach sterownika audio w jądrze
- między wątkiem wywołania zwrotnego AudioTrack lub AudioRecord a innymi wątkami aplikacji (nie mamy na to wpływu)
Typowe rozwiązania
Typowe rozwiązania to:
- wyłączanie funkcji przerwania
- muteksy dziedziczenia priorytetu
Wyłączenie przerw w działaniu jest niewykonalne w przestrzeni użytkowników Linuksa, nie działa w przypadku symetrycznych procesorów wieloprocesorowych (SMP).
Dziedziczenie priorytetów futeksy (szybkie muteksy w przestrzeni użytkownika) nie są stosowane w systemie audio, ponieważ są one stosunkowo ciężkie, i korzystają z usług zaufanego klienta.
Techniki używane przez Androida
Eksperymenty rozpoczęte od opcji „wypróbuj blokadę” i zablokować je po pewnym czasie. Są to nieblokujące i ograniczone warianty blokady muteksu . Funkcja blokowania i blokowania ze względu na limit czasu działała dość dobrze, ale nie narażony na kilka mało znanych trybów awarii: serwer nie będzie mieć dostępu do udostępnionego stanu, jeśli klient był zajęty, a łączny czas oczekiwania mógł być zbyt długie, jeśli następowała długa sekwencja niepowiązanych ze sobą blokad, przekroczono limit czasu.
Stosujemy też operacje niepodzielne Na przykład:
- zwiększ
- bitowe „lub”
- bitowe „i”
Wszystkie te elementy zwracają poprzednią wartość i zawierają niezbędne Bariery SMP. Wadą jest to, że mogą wymagać nieograniczonych ponownych prób. W praktyce odkryliśmy, że ponowna próba nie stanowi problemu.
Uwaga: operacje atomowe i ich interakcje z barierami pamięci są często źle zrozumiane i używane. Metody te obejmują tutaj, ale zalecamy też zapoznanie się SMP Primer na Androida .
Nadal mamy i wykorzystujemy większość z powyższych narzędzi, dodał(a) te techniki:
- Używaj nieblokującej funkcji zapisującego tylko z jednym czytnikiem Kolejki FIFO danych.
- Spróbuj kopiuj stanu, a nie udostępnij między wysokimi a wysokimi modułami o niskim priorytecie.
- Gdy trzeba udostępnić stan, ogranicz go do maksymalny rozmiar słowo do którego można uzyskać dostęp atomowo w ramach jednej magistrali bez ponownych prób.
- W przypadku złożonych stanów wielowyrazowych użyj kolejki stanu. Kolejka stanu to w zasadzie po prostu nieblokująca, jednoautorska FIFO kolejka używana na potrzeby stanu, a nie danych, z wyjątkiem zwijania zapisującego wypychanie sąsiadującej opcji.
- Zwróć uwagę na bariery pamięci pod kątem poprawności SMP.
- Zaufaj, ale zweryfikuj. Podczas udostępniania stan między procesami, zakładają, że państwo jest dobrze sformułowane. Na przykład sprawdź, czy indeksy mieści się w zakresie. Ta weryfikacja nie jest wymagana między wątkami w ramach tego samego procesu między wzajemnymi procesami zaufania (którymi zwykle mają taki sam identyfikator UID). Jest to też niepotrzebne w przypadku udostępniania. dane np. w PCM audio, gdy uszkodzenie jest nieistotne.
Algorytmy nieblokujące
Algorytmy nieblokujące były przedmiotem wielu ostatnich badań. Jednak z wyjątkiem kolejek FIFO dla pojedynczego odczytujących, są złożone i podatne na błędy.
Począwszy od Androida 4.2, znajdziesz nasze nieblokujące, zajęcia dla pojedynczego czytania/zapisującego w tych lokalizacjach:
- Frameworks/av/include/media/nbaio/
- Frameworks/av/media/libnbaio/
- Frameworks/av/services/audioflinger/StateQueue*
Zostały one opracowane specjalnie na potrzeby AudioFlinger i nie są do ogólnego przeznaczenia. Algorytmy nieblokujące są znane z tego, są trudne do debugowania. Możesz przyjrzeć się temu kodowi jako modelowi. lecz bądź że mogą występować błędy i nie ma gwarancji, że zajęcia odpowiednie do innych celów.
Programiści powinni zaktualizować część przykładowego kodu aplikacji OpenSL ES do używać nieblokujących algorytmów ani korzystać z biblioteki open source innej niż Android.
Opublikowaliśmy przykładową nieblokującą implementację FIFO przeznaczoną specjalnie dla:
kodu aplikacji. Zobacz te pliki w katalogu źródłowym platformy
frameworks/av/audio_utils
:
Narzędzia
Według naszej wiedzy nie ma automatycznych narzędzi do
na znalezienie odwrócenia priorytetów, zwłaszcza zanim to nastąpi. Niektóre
narzędzia do badań statycznej analizy kodu
są w stanie określić priorytety
czy użytkownik może uzyskać dostęp do całej bazy kodu. Oczywiście, jeśli
dowolny kod użytkownika (jako kod dla aplikacji)
lub stanowi dużą bazę kodu (jak w przypadku jądra systemu Linux i sterowników urządzeń),
analiza statyczna może być niepraktyczna. Najważniejsze jest to,
dokładnie przeczytaj kod, aby dobrze poznać cały kod
i interakcji. Narzędzia takie jak
systrace
oraz
ps -t -p
są przydatne do obserwacji odwrócenia priorytetów po wystąpieniu, ale
nie ujawnimy Ci z wyprzedzeniem.
Ostatnie słowo
Po całej dyskusji nie bój się muteksów. Wyciszenie przydają się w zwykłym zastosowaniu, pod warunkiem, że są prawidłowo zaimplementowane w zwykłych, niekrytycznych czasowo przypadkach użycia. Ale pomiędzy wysokimi w zadaniach o niskim priorytecie i w systemach pilnych może sprawiać problemy.