Wiadomości o usługach

Zwiększanie wydajności Androida: przedstawiamy AutoFDO dla jądra

Czas czytania: 4 minuty
Yabin Cui
Inżynier oprogramowania

Jesteśmy zespołem ds. łańcucha narzędzi Android LLVM. Jednym z naszych głównych priorytetów jest zwiększenie wydajności Androida za pomocą technik optymalizacji w ekosystemie LLVM. Stale szukamy sposobów na to, aby Android działał szybciej, płynniej i wydajniej.Większość naszych działań optymalizacyjnych odbywa się w przestrzeni użytkownika, ale jądro systemu pozostaje jego najważniejszym elementem. Z przyjemnością informujemy, że wprowadzamy do jądra Androida automatyczną optymalizację opartą na informacjach zwrotnych (AutoFDO), aby zapewnić użytkownikom znaczną poprawę wydajności.

Czym jest AutoFDO?

Podczas standardowego procesu kompilacji oprogramowania kompilator podejmuje tysiące drobnych decyzji, np. czy wstawić funkcję w kodzie, czy też która gałąź instrukcji warunkowej jest bardziej prawdopodobna, na podstawie statycznych wskazówek w kodzie. Chociaż te heurystyki są przydatne, nie zawsze dokładnie przewidują wykonanie kodu podczas rzeczywistego korzystania z telefonu.

AutoFDO zmienia to, wykorzystując rzeczywiste wzorce wykonania do kierowania kompilatorem. Wzorce te reprezentują najczęstsze ścieżki wykonywania instrukcji, które kod przyjmuje podczas rzeczywistego użycia. Są one rejestrowane przez zapisywanie historii rozgałęzień procesora. Chociaż te dane można zbierać z urządzeń we flocie, w przypadku jądra systemu operacyjnego syntetyzujemy je w środowisku laboratoryjnym, używając reprezentatywnych zbiorów zadań, takich jak uruchamianie 100 najpopularniejszych aplikacji. Do zbierania tych danych używamy profilera próbkowania, który określa, które części kodu są „gorące” (często używane), a które „zimne”. Gdy ponownie skompilujemy jądro z tymi profilami, kompilator będzie mógł podejmować znacznie trafniejsze decyzje dotyczące optymalizacji dostosowane do rzeczywistych obciążeń Androida.

Aby zrozumieć wpływ tej optymalizacji, zapoznaj się z tymi kluczowymi faktami:

  • W Androidzie jądro odpowiada za około 40% czasu procesora.
  • Używamy już AutoFDO do optymalizacji natywnych plików wykonywalnych i bibliotek w przestrzeni użytkownika, co pozwala nam uzyskać około 4-procentową poprawę czasu uruchamiania aplikacji na zimno i 1-procentową redukcję czasu rozruchu.

Zwycięstwa w świecie rzeczywistym

Dzięki wykorzystaniu profili z kontrolowanych środowisk laboratoryjnych zaobserwowaliśmy imponującą poprawę kluczowych wskaźników Androida. Profile te zostały zebrane za pomocą indeksowania i uruchamiania aplikacji oraz pomiarów na urządzeniach Pixel z jądrami 6.1, 6.6 i 6.12.

Najbardziej zauważalne ulepszenia są wymienione poniżej. Szczegółowe informacje o profilach AutoFDO dla tych wersji jądra znajdziesz w odpowiednich repozytoriach jądra Androida dla jąder android16-6.12android15-6.6.

boosting_2.png

To nie są tylko teoretyczne liczby. Przekłada się to na szybszy interfejs, szybsze przełączanie aplikacji, dłuższą żywotność baterii i ogólnie lepszą reakcję urządzenia na działania użytkownika.

Jak to działa: potok

Nasza strategia wdrażania obejmuje zaawansowany potok, który zapewnia aktualność profili i stabilność wyników.

boosting_3.png

Krok 1. Zbieranie profili

Do profilowania plików binarnych przestrzeni użytkownika używamy naszej wewnętrznej floty testowej, ale w przypadku ogólnego obrazu jądra (GKI) przeszliśmy na kontrolowane środowisko laboratoryjne. Oddzielenie profilowania od cyklu wydawania urządzeń umożliwia elastyczne i natychmiastowe aktualizacje niezależne od wdrożonych wersji jądra. Co najważniejsze, testy potwierdzają, że dane z laboratorium zapewniają wzrost wydajności porównywalny z tym, jaki można uzyskać w przypadku rzeczywistych flot.

  • Narzędzia i środowisko: na urządzeniach testowych instalujemy najnowszy obraz jądra i używamy narzędzia simpleperf do rejestrowania strumieni wykonywania instrukcji. Ten proces opiera się na możliwościach sprzętowych, które pozwalają rejestrować historię rozgałęzień, w szczególności na wykorzystaniu  rozszerzenia ARM Embedded Trace Extension (ETE)rozszerzenia ARM Trace Buffer Extension (TRBE) na urządzeniach Pixel.
  • Obciążenia:  tworzymy reprezentatywne obciążenie, korzystając z 100 najpopularniejszych aplikacji z zestawu testów zgodności aplikacji na Androida (C-Suite). Aby rejestrować jak najdokładniejsze dane, skupiamy się na:
    • Uruchamianie aplikacji: optymalizacja pod kątem najbardziej widocznych opóźnień użytkownika
    • Skanowanie aplikacji oparte na AI: symulowanie ciągłych, rozwijających się interakcji użytkownika.
    • Monitorowanie w skali całego systemu: rejestrowanie nie tylko działań aplikacji na pierwszym planie, ale też kluczowych zadań w tle i komunikacji międzyprocesowej.
  • Weryfikacja: ten zsyntetyzowany zbiór zadań wykazuje 85% podobieństwa do wzorców wykonania zebranych z naszej wewnętrznej floty.
  • Dane docelowe: powtarzając te testy wystarczająco często, rejestrujemy wzorce wykonania o wysokiej wierności, które dokładnie odzwierciedlają interakcje użytkowników z najpopularniejszymi aplikacjami w rzeczywistym świecie. Co więcej, ta rozszerzalna platforma umożliwia nam bezproblemowe integrowanie dodatkowych zbiorów zadań i testów porównawczych, aby zwiększyć zasięg.

Krok 2. Przetwarzanie profilu

Przetwarzamy wstępnie nieprzetworzone dane śledzenia, aby były czyste, skuteczne i gotowe do użycia przez kompilator.

  • Agregacja: konsolidujemy dane z wielu testów i urządzeń w jednym widoku systemu.
  • Konwersja:  konwertujemy surowe ślady na format profilu AutoFDO, w razie potrzeby odfiltrowując niepożądane symbole.
  • Przycinanie profili: przycinamy profile, aby usunąć dane dotyczące „zimnych” funkcji, co umożliwia stosowanie standardowej optymalizacji. Zapobiega to regresji w rzadko używanym kodzie i niepotrzebnemu zwiększaniu rozmiaru pliku binarnego.

Krok 3. Testowanie profilu

Przed wdrożeniem profile przechodzą rygorystyczną weryfikację, aby zapewnić stały wzrost wydajności bez ryzyka utraty stabilności.

  • Analiza profilu i pliku binarnego: ściśle porównujemy zawartość nowego profilu (w tym często używane funkcje, liczbę próbek i rozmiar profilu) z poprzednimi wersjami. Używamy też profilu do tworzenia nowego obrazu jądra, analizując pliki binarne, aby mieć pewność, że zmiany w sekcji tekstowej są zgodne z oczekiwaniami.
  • Weryfikacja wydajności: przeprowadzamy ukierunkowane testy porównawcze na nowym obrazie jądra. Potwierdza to, że utrzymuje ona wzrost skuteczności ustalony przez poprzednie wartości odniesienia.

Ciągłe aktualizacje

Kod z czasem naturalnie „odbiega” od pierwotnej wersji, więc statyczny profil z czasem straciłby skuteczność. Aby utrzymać najwyższą wydajność, nieustannie uruchamiamy potok, aby regularnie wprowadzać aktualizacje:

  • Regularne odświeżanie: odświeżamy profile w gałęziach LTS jądra Androida przed każdą wersją GKI, dzięki czemu każda kompilacja zawiera najnowsze dane profilu.
  • Przyszłe rozszerzenie: obecnie udostępniamy te aktualizacje w gałęziach android16-6.12android15-6.6. W przyszłości rozszerzymy obsługę na nowsze wersje GKI, takie jak nadchodząca wersja android17-6.18.

Zapewnianie stabilności

Często zadawane pytanie dotyczące optymalizacji opartej na profilu to, czy wiąże się ona z ryzykiem niestabilności. Ponieważ AutoFDO wpływa głównie na heurystyki kompilatora, takie jak wstawianie funkcji i układ kodu, a nie na logikę kodu źródłowego, zachowuje integralność funkcjonalną jądra. Ta technologia sprawdziła się już na dużą skalę, od lat stanowiąc standardową optymalizację bibliotek platformy Android, ChromeOS i infrastruktury serwerowej Google.

Aby jeszcze bardziej zagwarantować spójne działanie, stosujemy strategię „domyślnie konserwatywną”. Funkcje, które nie są uwzględnione w naszych profilach o wysokiej wierności, są optymalizowane za pomocą standardowych metod kompilatora. Dzięki temu „zimne” lub rzadko wykonywane części jądra działają dokładnie tak, jak w standardowej kompilacji, co zapobiega pogorszeniu wydajności lub nieoczekiwanemu zachowaniu w przypadkach skrajnych.

Co dalej

Obecnie wdrażamy AutoFDO w oddziałach android16-6.12android15-6.6. Poza tym początkowym wdrożeniem widzimy kilka obiecujących możliwości dalszego ulepszania tej technologii:

  • Większy zasięg: planujemy wdrożyć profile AutoFDO w nowszych wersjach jądra GKI i dodatkowych celach kompilacji poza obecną obsługą aarch64.
  • Optymalizacja modułu GKI: obecnie optymalizacja jest skupiona na głównym pliku binarnym jądra (vmlinux). Rozszerzenie AutoFDO na moduły GKI może przynieść korzyści w zakresie wydajności większej części podsystemu jądra.
  • Obsługa modułów dostawców: chcemy też obsługiwać AutoFDO w przypadku modułów dostawców utworzonych za pomocą zestawu Driver Development Kit (DDK). Dzięki temu, że obsługa jest już dostępna w naszym systemie kompilacji (Kleaf) i narzędziach do profilowania (simpleperf), dostawcy mogą stosować te same techniki optymalizacji w przypadku sterowników konkretnego sprzętu.
  • Szerszy zakres profili: istnieje możliwość zbierania profili z szerszego zakresu najważniejszych ścieżek użytkowników (CUJ) w celu ich optymalizacji.

Wprowadzając AutoFDO do jądra Androida, dbamy o to, aby podstawy systemu operacyjnego były zoptymalizowane pod kątem codziennego korzystania z urządzenia.

Autor:

Czytaj dalej