Wiadomości o usługach

Zwiększanie wydajności Androida: wprowadzenie AutoFDO w jądrze

Czas czytania: 4 min
Wyświetl profil Charlesa Mungera
Yabin Cui Inżynier oprogramowania

Jesteśmy zespołem ds. Androida LLVM Toolchain. 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), która przyniesie 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 miejscu wywołania i 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ń flotowych, 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 bardziej przemyślane decyzje dotyczące optymalizacji, dostosowane do rzeczywistych obciążeń Androida.

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

  • Na 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-procentowe skrócenie czasu rozruchu.

Zwycięstwa w rzeczywistych testach wydajności

Dzięki wykorzystaniu profili z kontrolowanych środowisk laboratoryjnych zaobserwowaliśmy imponujące ulepszenia w zakresie kluczowych wskaźników Androida. Te profile 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 wymieniliśmy 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.12 i android15-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ą responsywność urządzenia dla 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 floty testów wewnętrznych, 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, natychmiastowe aktualizacje niezależne od wdrożonych wersji jądra. Co ważne, 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) i 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żytkowników.
    • Monitorowanie w skali całego systemu: rejestrowanie nie tylko aktywności aplikacji na pierwszym planie, ale też krytycznych obciążeń w tle i komunikacji międzyprocesowej.
  • Weryfikacja: ten syntetyczny zbiór zadań wykazuje 85% podobieństwa do wzorców wykonywania zebranych z naszej wewnętrznej floty.
  • Dane docelowe: dzięki wielokrotnemu powtarzaniu tych testów rejestrujemy wzorce wykonywania 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 przebiegów testów i urządzeń w jednym widoku systemu.
  • Konwersja:  konwertujemy nieprzetworzone ś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 pozwala na 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łe zwiększanie 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 „dryfuje”, więc statyczny profil z czasem straciłby skuteczność. Aby utrzymać najwyższą wydajność, stale 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.12 i android15-6.6. W przyszłości rozszerzymy obsługę o nowsze wersje GKI, takie jak nadchodząca android17-6.18.

Zapewnianie stabilności

Często zadawane pytanie dotyczące optymalizacji opartej na profilu to, czy wiąże się ona z ryzykiem utraty stabilności. Ponieważ AutoFDO wpływa głównie na heurystykę kompilatora, taką jak wstawianie funkcji i układ kodu, a nie zmienia logiki kodu źródłowego, zachowuje integralność funkcjonalną jądra. Ta technologia sprawdziła się już na dużą skalę, ponieważ od lat jest 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 przy użyciu 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.12 i android15-6.6. Poza tym początkowym wdrożeniem widzimy kilka obiecujących możliwości dalszego ulepszania tej technologii:

  • Zwiększony zasięg: planujemy wdrożyć profile AutoFDO w nowszych wersjach jądra GKI i dodatkowych docelowych wersjach 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 wsparcie jest już dostępne w naszym systemie kompilacji (Kleaf) i narzędziach do profilowania (simpleperf), dostawcy mogą stosować te same techniki optymalizacji w przypadku sterowników konkretnych urządzeń.
  • Szerszy zakres profili: istnieje możliwość zbierania profili z większej liczby 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.

Autorzy:
Czytaj dalej