Bu belge, belirli Android cihazlarının önyükleme sürelerini iyileştirmeye yönelik iş ortaklarına rehberlik sağlar. Kullanıcıların aygıtı kullanmadan önce önyüklemenin tamamlanmasını beklemesi gerektiğinden, önyükleme süresi sistem performansının önemli bir bileşenidir. Soğuk başlatmanın daha sık gerçekleştiği otomobiller gibi cihazlar için, hızlı başlatma süresine sahip olmak kritik öneme sahiptir (hiç kimse yalnızca bir navigasyon hedefi girmek için onlarca saniye beklemekten hoşlanmaz).
Android 8.0, çeşitli bileşenlerdeki çeşitli iyileştirmeleri destekleyerek önyükleme sürelerinin azaltılmasına olanak tanır. Aşağıdaki tabloda bu performans iyileştirmeleri özetlenmektedir (Google Pixel ve Pixel XL cihazlarda ölçülmüştür).
Bileşen | Gelişim |
---|---|
Önyükleyici |
|
Cihaz çekirdeği |
|
G/Ç ayarı |
|
init.*.rc |
|
Önyükleme animasyonu |
|
SELinux politikası | genfscon tarafından 0,2 sn tasarruf edildi |
Önyükleyiciyi optimize edin
Daha iyi önyükleme süreleri için önyükleyiciyi optimize etmek için:
- Günlüğe kaydetme için:
- Çok sayıda günlük kaydı uzun zaman alabileceğinden, UART'a günlük yazmayı devre dışı bırakın. (Google Pixel cihazlarda önyükleyiciyi 1,5 saniye yavaşlattığını gördük).
- Yalnızca hata durumlarını günlüğe kaydedin ve geri almak için diğer bilgileri ayrı bir mekanizmayla belleğe kaydetmeyi düşünün.
- Çekirdek sıkıştırmasını açmak için, çağdaş donanımda GZIP yerine LZ4 kullanmayı düşünün (örnek yama ). Farklı çekirdek sıkıştırma seçeneklerinin farklı yükleme ve açma sürelerine sahip olabileceğini ve bazı seçeneklerin, özel donanımınız için diğerlerinden daha iyi çalışabileceğini unutmayın.
- Geri dönüş/özel mod girişi için gereksiz bekleme sürelerini kontrol edin ve bunları en aza indirin.
- Önyükleyicide harcanan önyükleme süresini çekirdeğe cmdline olarak aktarın.
- CPU saatini kontrol edin ve çekirdek yükleme ve G/Ç'yi başlatma için paralelleştirmeyi (çok çekirdekli destek gerektirir) düşünün.
G/Ç verimliliğini optimize edin
G/Ç verimliliğini artırmak, önyükleme süresini hızlandırmak açısından kritik öneme sahiptir ve gerekli olmayan herhangi bir şeyin okunması, önyükleme sonrasına ertelenmelidir (Google Pixel'de, önyükleme sırasında yaklaşık 1,2 GB veri okunur).
Dosya sistemini ayarlayın
Linux çekirdeği ileri okuma, bir dosya baştan okunduğunda veya bloklar sırayla okunduğunda devreye girerek G/Ç zamanlayıcı parametrelerinin özellikle önyükleme için (normal uygulamalardan farklı bir iş yükü karakterizasyonuna sahip) ayarlanmasını gerekli kılar.
Kesintisiz (A/B) güncellemeleri destekleyen cihazlar, ilk açılışta dosya sistemi ayarlamasından büyük ölçüde yararlanır (örneğin, Google Pixel'de 20'ler). Örnek olarak Google Pixel için aşağıdaki parametreleri ayarladık:
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 ...
Çeşitli
- Çekirdek yapılandırması DM_VERITY_HASH_PREFETCH_MIN_SIZE (varsayılan boyut 128'dir) kullanarak dm-verity karma önceden getirme boyutunu açın.
- Daha iyi dosya sistemi kararlılığı ve her önyüklemede meydana gelen zorunlu denetimin düşürülmesi için BoardConfig.mk'de TARGET_USES_MKE2FS ayarını yaparak yeni ext4 oluşturma aracını kullanın.
G/Ç'yi analiz edin
Önyükleme sırasında G/Ç etkinliklerini anlamak için çekirdek ftrace verilerini kullanın (aynı zamanda systrace tarafından da kullanılır):
trace_event=block,ext4 in BOARD_KERNEL_CMDLINE
Her bir dosyanın dosya erişimini dökümlemek için çekirdekte aşağıdaki değişiklikleri yapın (yalnızca geliştirme çekirdeği; üretim çekirdeklerinde kullanmayın):
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);
Önyükleme performansını analiz etmeye yardımcı olması için aşağıdaki komut dosyalarını kullanın.
-
system/extras/boottime_tools/bootanalyze/bootanalyze.py
Önyükleme sürecindeki önemli adımların dökümüyle önyükleme süresini ölçer. -
system/extras/boottime_tools/io_analysis/check_file_read.py boot_trace
Her dosya için erişim bilgisi sağlar. -
system/extras/boottime_tools/io_analysis/check_io_trace_all.py boot_trace
Sistem düzeyinde döküm verir.
init.*.rc'yi optimize edin
Init, çekirdekten çerçevenin kurulmasına kadar geçen köprüdür ve cihazlar genellikle farklı başlatma aşamalarında birkaç saniye harcar.
Görevleri paralel olarak çalıştırın
Mevcut Android init aşağı yukarı tek iş parçacıklı bir işlem olsa da, yine de bazı görevleri paralel olarak gerçekleştirebilirsiniz.
- Bir kabuk komut dosyası hizmetinde yavaş komutları yürütün ve daha sonra belirli bir özelliği bekleyerek buna katılın. Android 8.0, bu kullanım durumunu yeni
wait_for_property
komutuyla destekler. - İnit'teki yavaş işlemleri tanımlayın. Sistem, exec/wait_for_prop başlatma komutunu veya uzun süren herhangi bir eylemi (Android 8.0'da, 50 ms'den uzun süren herhangi bir komut) günlüğe kaydeder. Örneğin:
init: Command 'wait_for_coldboot_done' action=wait_for_coldboot_done returned 0 took 585.012ms
Bu günlüğün incelenmesi iyileştirme fırsatlarına işaret edebilir.
- Hizmetleri başlatın ve kritik yoldaki çevresel aygıtları erkenden etkinleştirin. Örneğin, bazı SOC'ler SurfaceFlinger'ı başlatmadan önce güvenlikle ilgili hizmetlerin başlatılmasını gerektirir. ServiceManager "hizmet için bekle" ifadesini döndürdüğünde sistem günlüğünü inceleyin; bu genellikle önce bağımlı bir hizmetin başlatılması gerektiğinin bir işaretidir.
- init.*.rc dosyasındaki kullanılmayan hizmetleri ve komutları kaldırın. Başlangıç aşamasında kullanılmayan herhangi bir şey, önyüklemenin tamamlanmasına ertelenmelidir.
Not: Özellik hizmeti, init işleminin bir parçasıdır, bu nedenle, init yerleşik komutlarla meşgulse, önyükleme sırasında setproperty
çağrılması uzun bir gecikmeye neden olabilir.
Zamanlayıcı ayarını kullan
Erken önyükleme için zamanlayıcı ayarını kullanın. Google Pixel'den örnek:
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
Bazı hizmetlerin önyükleme sırasında öncelik artışına ihtiyacı olabilir. Örnek:
init.zygote64.rc: service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server class main priority -20 user root ...
Zigota erken başlayın
Dosya tabanlı şifrelemeye sahip cihazlar, zigot başlatma tetikleyicisinde zigotu daha erken başlatabilir (varsayılan olarak zigot, zigot başlangıcından çok daha sonra olan ana sınıfta başlatılır). Bunu yaparken zigotun tüm CPU'larda çalışmasına izin verdiğinizden emin olun (çünkü yanlış cpuset ayarı zigotun belirli CPU'larda çalışmasına neden olabilir).
Güç tasarrufunu devre dışı bırak
Cihaz önyüklemesi sırasında UFS ve/veya CPU regülatörü gibi bileşenler için güç tasarrufu ayarı devre dışı bırakılabilir.
Dikkat: Verimlilik için şarj cihazı modunda güç tasarrufu etkinleştirilmelidir.
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
Kritik olmayan başlatmayı ertele
ZRAM gibi kritik olmayan başlatma, boot_complete
ertelenebilir.
on property:sys.boot_completed=1 # Enable ZRAM on boot_complete swapon_all /vendor/etc/fstab.${ro.hardware}
Önyükleme animasyonunu optimize edin
Önyükleme animasyonunu optimize etmek için aşağıdaki ipuçlarını kullanın.
Erken başlatmayı yapılandırın
Android 8.0, kullanıcı verileri bölümünü bağlamadan önce önyükleme animasyonunun erken başlatılmasını sağlar. Bununla birlikte, Android 8.0'da yeni ext4 araç zincirini kullanırken bile fsck, güvenlik nedeniyle hala periyodik olarak tetikleniyor ve bu da önyükleme animasyonu hizmetinin başlatılmasında gecikmeye neden oluyor.
Önyükleme animasyonunun erken başlamasını sağlamak için fstab montajını iki aşamaya bölün:
- İlk aşamada, yalnızca çalıştırma denetimi gerektirmeyen bölümleri (
system/
vevendor/
gibi) bağlayın, ardından önyükleme animasyon hizmetlerini ve bağımlılıklarını (servicemanager ve Surfaceflinger gibi) başlatın. - İkinci aşamada, çalışma kontrolleri gerektiren bölümleri (
data/
gibi) bağlayın.
Önyükleme animasyonu, fsck'ten bağımsız olarak çok daha hızlı (ve sabit sürede) başlatılacaktır.
Temiz bitir
Çıkış sinyalini aldıktan sonra, önyükleme animasyonu, uzunluğu önyükleme süresini yavaşlatabilen son kısmı oynatır. Hızlı bir şekilde önyüklenen bir sistemin, yapılan iyileştirmeleri etkili bir şekilde gizleyebilecek uzun animasyonlara ihtiyacı yoktur. Hem tekrar eden döngüyü hem de finali kısa tutmanızı öneririz.
SELinux'u optimize edin
Daha iyi önyükleme süreleri için SELinux'u optimize etmek amacıyla aşağıdaki ipuçlarını kullanın.
- Temiz normal ifadeler (regex) kullanın . Kötü biçimlendirilmiş normal ifade,
file_contexts
içindekisys/devices
için SELinux politikasını eşleştirirken çok fazla ek yüke yol açabilir. Örneğin,/sys/devices/.*abc.*(/.*)?
normal ifadesi yanlışlıkla "abc" içeren tüm/sys/devices
alt dizinlerinin taranmasını zorlar ve hem/sys/devices/abc
hem de/sys/devices/xyz/abc
için eşleşmeleri etkinleştirir. Bu normal ifade/sys/devices/[^/]*abc[^/]*(/.*)?
yalnızca/sys/devices/abc
için eşleşmeyi etkinleştirir. - Etiketleri genfscon'a taşıyın . Bu mevcut SELinux özelliği, dosya eşleştirme öneklerini SELinux ikili dosyasındaki çekirdeğe aktarır ve burada çekirdek bunları çekirdek tarafından oluşturulan dosya sistemlerine uygular. Bu aynı zamanda çekirdek tarafından oluşturulan yanlış etiketlenmiş dosyaların düzeltilmesine de yardımcı olur ve yeniden etiketleme gerçekleşmeden önce bu dosyalara erişmeye çalışan kullanıcı alanı işlemleri arasında oluşabilecek yarış koşullarını önler.
Araçlar ve yöntemler
Optimizasyon hedeflerine yönelik verileri toplamanıza yardımcı olması için aşağıdaki araçları kullanın.
Önyükleme şeması
Bootchart, tüm sistem için tüm süreçlerin CPU ve I/O yük dökümünü sağlar. Sistem görüntüsünün yeniden oluşturulmasını gerektirmez ve systrace'e dalmadan önce hızlı bir sağlık kontrolü olarak kullanılabilir.
Önyükleme grafiğini etkinleştirmek için:
adb shell 'touch /data/bootchart/enabled'
adb reboot
Önyüklemeden sonra önyükleme grafiğini getirin:
$ANDROID_BUILD_TOP/system/core/init/grab-bootchart.sh
İşiniz bittiğinde, verilerin her seferinde toplanmasını önlemek için /data/bootchart/enabled
silin.
bootchart.png
mevcut olmadığını belirten bir hata mesajı alıyorsanız aşağıdakileri yapın:- Aşağıdaki komutları çalıştırın:
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
-
$ANDROID_BUILD_TOP/system/core/init/grab-bootchart.sh
pybootchartgui
yerel kopyasına işaret edecek şekilde güncelleyin (~/Documents/bootchart/pybootchartgui.py
konumunda bulunur)
Systrace
Systrace, başlatma sırasında hem çekirdek hem de Android izlerinin toplanmasına olanak tanır. Systrace'in görselleştirilmesi, başlatma sırasında belirli bir sorunun analiz edilmesine yardımcı olabilir. (Ancak, tüm önyükleme sırasındaki ortalama sayıyı veya birikmiş sayıyı kontrol etmek için doğrudan çekirdek izine bakmak daha kolaydır).
Önyükleme sırasında systrace'i etkinleştirmek için:
-
frameworks/native/cmds/atrace/atrace.rc
değiştirin:write /sys/kernel/debug/tracing/tracing_on 0 write /sys/kernel/tracing/tracing_on 0
İle:
# write /sys/kernel/debug/tracing/tracing_on 0 # write /sys/kernel/tracing/tracing_on 0
-
device.mk
dosyasına şu satırı ekleyin:PRODUCT_PROPERTY_OVERRIDES += debug.atrace.tags.enableflags=802922 PRODUCT_PROPERTY_OVERRIDES += persist.traced.enable=0
- Aygıtın
BoardConfig.mk
dosyasına aşağıdakini ekleyin:BOARD_KERNEL_CMDLINE := ... trace_buf_size=64M trace_event=sched_wakeup,sched_switch,sched_blocked_reason,sched_cpu_hotplug
- Cihaza özel
init.rc
dosyasına aşağıdakini ekleyin: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
Önyüklemeden sonra izlemeyi getir:
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
Bu, izlemeyi etkinleştirir (varsayılan olarak devre dışıdır).
Ayrıntılı G/Ç analizi için ayrıca blok ve ext4 ve f2fs'yi ekleyin.