Ten dokument zawiera wskazówki dla partnerów, które pomogą Ci skrócić czas uruchamiania w określonych przypadkach Urządzenia z Androidem. Czas uruchamiania to ważny element wydajności systemu, użytkownicy muszą poczekać na zakończenie uruchamiania, zanim będą mogli korzystać z urządzenia. Urządzenia np. w przypadku samochodów, które uruchamiają się częściej na zimno, czas jest krytyczny (nikt nie lubi czekać dziesiątki sekund tylko po to, aby wpisać miejsce docelowe nawigacji).
Android 8.0 umożliwia skrócenie czasu uruchamiania dzięki obsłudze kilku ulepszeń z wielu komponentów. Te dane są przedstawione w tabeli poniżej (zmierzone na urządzeniach Google Pixel i Pixel XL).
Komponent | Poprawa |
---|---|
Program rozruchowy |
|
Jądro urządzenia |
|
Dostrajanie I/O |
|
init.*.rc |
|
Animacja podczas uruchamiania |
|
Zasada SELinux | Zapisane 0,2 s przez: genfscon |
Optymalizacja programu rozruchowego
Aby zoptymalizować program rozruchowy i skrócić czas uruchamiania:
- Do logowania:
- Wyłącz zapisywanie dzienników do UART, ponieważ może to zająć dużo czasu z wieloma logowanie. Na urządzeniach Google Pixel spowalniają one program rozruchowy o 1, 5 s.
- Rejestruj tylko błędy i rozważ zapisanie innych informacji w pamięci z osobnym mechanizmem ich pobierania.
- Rozważenie dekompresji jądra systemu LZ4 w nowoczesnym sprzęcie zamiast GZIP (przykładowy plik patch). Pamiętaj, że: różne opcje kompresji jądra mogą mieć różne i niektóre opcje mogą działać lepiej niż inne i konkretnego sprzętu.
- Sprawdź niepotrzebne czasy oczekiwania na odbijanie wiadomości/wprowadzanie w trybie specjalnym i minimalizuj .
- Przekazuj czas rozruchu w programie rozruchowym do jądra jako cmdline.
- Sprawdź zegar procesora i rozważ zastosowanie równoległego sterowania (wymaga obsługi wielu rdzeni) do wczytywania jądra i inicjowania operacji wejścia-wyjścia.
Optymalizuj wydajność I/O
Poprawa wydajności wejścia-wyjścia ma kluczowe znaczenie dla przyspieszenia rozruchu. wszystkie niepotrzebne niepotrzebne rzeczy należy odłożyć do czasu uruchomienia (w telefonie Google Pixel odczytywane jest około 1,2 GB danych podczas uruchamiania urządzenia).
Dostrój system plików
Odczyt jądra systemu Linux rozpoczyna się, gdy plik jest odczytywany od początku lub gdy bloki są odczytywane sekwencyjnie, co wymaga dostrojenia algorytmu szeregowania wejścia-wyjścia parametry służące do uruchamiania (który obejmuje inny zbiór zadań, niż zwykłe aplikacje).
Urządzenia obsługujące bezproblemowe aktualizacje typu A/B w dużym stopniu korzystają z systemu plików. dostrajanie przy pierwszym uruchomieniu (np. 20 s w przypadku Google Pixel). Na przykład stworzyliśmy te parametry dla telefonu Google Pixel:
on late-fs # boot time fs tune # boot time fs tune write /sys/block/sda/queue/iostats 0 write /sys/block/sda/queue/scheduler cfq write /sys/block/sda/queue/iosched/slice_idle 0 write /sys/block/sda/queue/read_ahead_kb 2048 write /sys/block/sda/queue/nr_requests 256 write /sys/block/dm-0/queue/read_ahead_kb 2048 write /sys/block/dm-1/queue/read_ahead_kb 2048 on property:sys.boot_completed=1 # end boot time fs tune write /sys/block/sda/queue/read_ahead_kb 512 ...
Różne
- Włącz rozmiar szyfrowania z wyprzedzeniem dm-verity za pomocą konfiguracji jądra DM_VERITY_HASH_PREFETCH_MIN_SIZE (rozmiar domyślny to 128).
- W celu zwiększenia stabilności systemu plików oraz rezygnacji z wymuszonego sprawdzania przy każdym rozruchu, używaj nowego narzędzia do generowania ext4, ustawiając TARGET_USES_MKE2FS w BoardConfig.mk
Analizuj I/O
Aby zrozumieć działania wejścia-wyjścia podczas uruchamiania, użyj danych śledzenia jądra (służą one również systrace):
trace_event=block,ext4 in BOARD_KERNEL_CMDLINE
Aby podzielić dostęp do poszczególnych plików, wprowadź następujące zmiany w jądrze: (tylko jądro dla programistów; nie należy go używać w jądrze produkcyjnym):
diff --git a/fs/open.c b/fs/open.c index 1651f35..a808093 100644 --- a/fs/open.c +++ b/fs/open.c @@ -981,6 +981,25 @@ } EXPORT_SYMBOL(file_open_root); +static void _trace_do_sys_open(struct file *filp, int flags, int mode, long fd) +{ + char *buf; + char *fname; + + buf = kzalloc(PAGE_SIZE, GFP_KERNEL); + if (!buf) + return; + fname = d_path(&filp-<f_path, buf, PAGE_SIZE); + + if (IS_ERR(fname)) + goto out; + + trace_printk("%s: open(\"%s\", %d, %d) fd = %ld, inode = %ld\n", + current-<comm, fname, flags, mode, fd, filp-<f_inode-<i_ino); +out: + kfree(buf); +} + long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode) { struct open_flags op; @@ -1003,6 +1022,7 @@ } else { fsnotify_open(f); fd_install(fd, f); + _trace_do_sys_open(f, flags, mode, fd);
Aby przeanalizować wydajność uruchamiania, użyj tych skryptów.
system/extras/boottime_tools/bootanalyze/bootanalyze.py
Mierzy czas uruchamiania z podziałem na ważne kroki procesu uruchamiania.system/extras/boottime_tools/io_analysis/check_file_read.py boot_trace
– podaje informacje o dostępie do każdego pliku.system/extras/boottime_tools/io_analysis/check_io_trace_all.py boot_trace
Udostępnia podział na poziomie systemu.
Optymalizuj init.*.rc
Jest to most z jądra systemu aż do ustanowienia platformy. urządzenia zwykle spędzają kilka sekund na różnych etapach inicjowania.
Równoległe uruchamianie zadań
Bieżąca inicjalizacja Androida jest bardziej lub mniej niż procesem jednowątkowym, nadal mogą wykonywać niektóre zadania równolegle.
- uruchamiać powolne polecenia w usłudze skryptów powłoki i łączyć je później,
i czekania na określoną właściwość. Android 8.0 obsługuje ten przypadek użycia
wait_for_property
. - Zidentyfikuj powolne operacje w inicjowaniu. System zarejestruje polecenie init.
exec/wait_for_prop lub inne, długotrwałe działanie (w Androidzie 8.0 dowolne polecenie
trwa dłużej niż 50 ms). Na przykład:
init: Command 'wait_for_coldboot_done' action=wait_for_coldboot_done returned 0 took 585.012ms
Zaglądanie do tego dziennika może wskazywać możliwości wprowadzenia ulepszeń.
- Szybko uruchom usługi i włącz urządzenia peryferyjne na ścieżce krytycznej. Dla: na przykład niektóre konta SOC wymagają uruchomienia usług związanych z zabezpieczeniami przed rozpoczęciem SurfaceFlinger. Sprawdź dziennik systemowy, gdy ServiceManager zwróci wartość „Poczekaj na” „usługa” – zwykle oznacza to, że trzeba uruchomić usługę zależną .
- Usuń wszystkie nieużywane usługi i polecenia z pliku init.*.rc. Wszystkie elementy nieużywane inicjowanie na wczesnym etapie powinno być odroczone do ukończenia uruchamiania.
Uwaga: usługa obiektu jest częścią procesu inicjowania, więc wywołanie
setproperty
podczas uruchamiania może spowodować długie opóźnienie, jeśli inicjowanie jest zajęte
z wbudowanymi poleceniami.
Używaj dostrajania algorytmu szeregowania
Użyj dostrajania algorytmu szeregowania na potrzeby wcześniejszego rozruchu. Przykład z telefonu Google Pixel:
on init # boottime stune write /dev/stune/schedtune.prefer_idle 1 write /dev/stune/schedtune.boost 100 on property:sys.boot_completed=1 # reset stune write /dev/stune/schedtune.prefer_idle 0 write /dev/stune/schedtune.boost 0 # or just disable EAS during boot on init write /sys/kernel/debug/sched_features NO_ENERGY_AWARE on property:sys.boot_completed=1 write /sys/kernel/debug/sched_features ENERGY_AWARE
Niektóre usługi mogą wymagać wzmocnienia priorytetu podczas uruchamiania. Przykład:
init.zygote64.rc: service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server class main priority -20 user root ...
Zacznij zygote wcześniej
Urządzenia z szyfrowaniem opartym na plikach mogą uruchomić zygote wcześniej podczas uruchamiania zygote-start aktywator (domyślnie zygote jest uruchamiana na poziomie głównej klasy, która jest znacznie późniejsza niż zygote-start). Wykonując tę czynność, zezwól na uruchomienie zygote na wszystkich procesorach ( nieprawidłowe ustawienie cpuset może wymusić działanie Zygote na określonych procesorach).
Wyłącz oszczędzanie energii
ustawienie oszczędzania energii przez komponenty takie jak UFS lub procesor podczas uruchamiania urządzenia; gubernatora można wyłączyć.
Uwaga: oszczędzanie energii powinno być włączone w trybu ładowania, aby oszczędzać energię.
on init # Disable UFS powersaving write /sys/devices/soc/${ro.boot.bootdevice}/clkscale_enable 0 write /sys/devices/soc/${ro.boot.bootdevice}/clkgate_enable 0 write /sys/devices/soc/${ro.boot.bootdevice}/hibern8_on_idle_enable 0 write /sys/module/lpm_levels/parameters/sleep_disabled Y on property:sys.boot_completed=1 # Enable UFS powersaving write /sys/devices/soc/${ro.boot.bootdevice}/clkscale_enable 1 write /sys/devices/soc/${ro.boot.bootdevice}/clkgate_enable 1 write /sys/devices/soc/${ro.boot.bootdevice}/hibern8_on_idle_enable 1 write /sys/module/lpm_levels/parameters/sleep_disabled N on charger # Enable UFS powersaving write /sys/devices/soc/${ro.boot.bootdevice}/clkscale_enable 1 write /sys/devices/soc/${ro.boot.bootdevice}/clkgate_enable 1 write /sys/devices/soc/${ro.boot.bootdevice}/hibern8_on_idle_enable 1 write /sys/class/typec/port0/port_type sink write /sys/module/lpm_levels/parameters/sleep_disabled N
Wstrzymaj inicjowanie niekrytyczne
Inicjowanie niekrytyczne, na przykład ZRAM, można odroczyć do boot_complete
.
on property:sys.boot_completed=1 # Enable ZRAM on boot_complete swapon_all /vendor/etc/fstab.${ro.hardware}
Optymalizacja animacji rozruchu
Skorzystaj z poniższych wskazówek, aby zoptymalizować animację rozruchu.
Skonfiguruj wczesny start
Android 8.0 umożliwia wcześniejsze uruchomienie animacji rozruchu, przed podłączeniem danych użytkownika partycji danych. Jednak nawet w przypadku korzystania z nowego łańcucha narzędzi ext4 w Androidzie 8.0, fsck jest nadal okresowo uruchamiana ze względów bezpieczeństwa, powodując opóźnienie uruchamianie usługi uruchamiania animacji.
Aby uruchomić animację rozruchu wcześniej, podziel element montowania fstab na 2 fazy:
- Na wczesnym etapie podłącz tylko partycje (np.
system/
ivendor/
), które nie wymagają uruchomienia a następnie uruchomić usługi animacji i ich zależności (takie jak Servicemanager i Surfaceflinger). - W drugim etapie podłącz partycje (takie jak
data/
), które ale wymagają uruchamiania testów.
Animacja uruchamiania uruchamia się znacznie szybciej (i w stałym czasie) niezależnie od do kurwy.
Wykończ czyszczenie
Po otrzymaniu sygnału wyjściowego animacja uruchamiana odtworzy ostatnią część, co może spowolnić uruchamianie. System, który uruchamia się szybko, nie wymaga animacje, które mogłyby ukryć wprowadzone ulepszenia. Zalecamy przez co pętla powtarzania i koniec są krótkie.
Optymalizacja SELinux
Skorzystaj z poniższych wskazówek, aby zoptymalizować SELinux i skrócić czas uruchamiania.
- Używaj przejrzystych wyrażeń regularnych. Niepoprawnie sformułowane wyrażenie regularne
może znacznie zwiększyć koszty podczas dopasowywania zasad SELinux dla
sys/devices
wfile_contexts
. Na przykład wyrażenie regularne Funkcja/sys/devices/.*abc.*(/.*)?
błędnie wymusza skanowanie wszystkich elementów/sys/devices
podkatalogów zawierających słowo „abc”, co umożliwia dopasowanie zarówno dla/sys/devices/abc
, jak i/sys/devices/xyz/abc
. Rozszerzenie tego wyrażenia regularnego do wersji/sys/devices/[^/]*abc[^/]*(/.*)?
sprawi, włącz dopasowanie tylko dla adresu/sys/devices/abc
. - Przenieś etykiety do genfscon. Ta istniejąca funkcja SELinux przekazuje prefiksy dopasowania plików do jądra systemu pliku binarnego SELinux, w którym jądro stosuje go do wygenerowanych w jądrze funkcji systemów plików. Pomaga to również w naprawianiu błędnie oznaczonych plików utworzonych w jądrze, warunki wyścigu, które mogą wystąpić między procesami przestrzeni użytkownika usiłującymi uzyskać dostęp przed zmianą etykiet.
Narzędzia i metody
Opisane poniżej narzędzia pomogą Ci zbierać dane na potrzeby celów optymalizacji.
Wykres rozruchowy
Wykres rozruchowy udostępnia zestawienie obciążenia procesora i wejścia-wyjścia dla wszystkich procesów w całym procesie systemu. Nie wymaga odbudowy obrazu systemu i można go użyć należy sprawdzić poprawność przed przystąpieniem do systrace.
Aby włączyć wykres rozruchowy:
adb shell 'touch /data/bootchart/enabled'
adb reboot
Po uruchomieniu pobierz wykres rozruchowy:
$ANDROID_BUILD_TOP/system/core/init/grab-bootchart.sh
Gdy skończysz, usuń /data/bootchart/enabled
, aby zapobiec gromadzeniu
dane za każdym razem.
bootchart.png
nie istnieje, zrób
następujące:
- Uruchom te polecenia:
sudo apt install python-is-python3
cd ~/Documents
git clone https://github.com/xrmx/bootchart.git
cd bootchart/pybootchartgui
mv main.py.in main.py
- Zaktualizuj urządzenie
$ANDROID_BUILD_TOP/system/core/init/grab-bootchart.sh
aby wskazać lokalną kopię plikupybootchartgui
(lokalizacja:~/Documents/bootchart/pybootchartgui.py
)
Sístrače
Systrace umożliwia zbieranie logów czasu jądra i Androida podczas uruchamiania. Wizualizacja systrace może pomóc w analizie konkretnego problemu podczas uruchamiania. (Aby jednak sprawdzić średnią lub skumulowaną liczbę w okresie podczas rozruchu, łatwiej jest bezpośrednio zajrzeć do logu jądra).
Aby włączyć systrace podczas uruchamiania:
- W
frameworks/native/cmds/atrace/atrace.rc
zmień:write /sys/kernel/debug/tracing/tracing_on 0 write /sys/kernel/tracing/tracing_on 0
Aby:
# write /sys/kernel/debug/tracing/tracing_on 0 # write /sys/kernel/tracing/tracing_on 0
- W pliku
device.mk
dodaj ten wiersz:PRODUCT_PROPERTY_OVERRIDES += debug.atrace.tags.enableflags=802922 PRODUCT_PROPERTY_OVERRIDES += persist.traced.enable=0
- W pliku
BoardConfig.mk
urządzenia dopisz:BOARD_KERNEL_CMDLINE := ... trace_buf_size=64M trace_event=sched_wakeup,sched_switch,sched_blocked_reason,sched_cpu_hotplug
- W pliku
init.rc
powiązanym z konkretnym urządzeniem dodaj:on property:sys.boot_completed=1 // This stops tracing on boot complete write /d/tracing/tracing_on 0 write /d/tracing/events/ext4/enable 0 write /d/tracing/events/f2fs/enable 0 write /d/tracing/events/block/enable 0
-
Po uruchomieniu pobierz log czasu:
adb root && adb shell atrace --async_stop -z -c -o /data/local/tmp/boot_trace
adb pull /data/local/tmp/boot_trace
$ANDROID_BUILD_TOP/external/chromium-trace/systrace.py --from-file=boot_trace
Umożliwia to śledzenie (domyślnie jest ono wyłączone).
Aby przeprowadzić szczegółową analizę wejścia-wyjścia, dodaj też bloki oraz ext4 i f2fs.