Önyükleme Süresi Optimizasyonu

Bu sayfa, önyükleme süresini iyileştirmek için aralarından seçim yapabileceğiniz bir dizi ipucu sağlar.

Modüllerden hata ayıklama sembollerini çıkarın

Bir üretim cihazında hata ayıklama sembollerinin çekirdekten çıkarılmasına benzer şekilde, modüllerdeki hata ayıklama sembollerini de çıkardığınızdan emin olun. Hata ayıklama sembollerinin modüllerden çıkarılması, aşağıdakileri azaltarak önyükleme süresine yardımcı olur:

  • İkili dosyaları flaştan okumak için gereken süre.
  • Ramdisk'in sıkıştırmasını açmak için gereken süre.
  • Modüllerin yüklenmesi için gereken süre.

Hata ayıklama sembolünün modüllerden çıkarılması , önyükleme sırasında birkaç saniye kazandırabilir.

Sembol ayırma, Android platformu yapısında varsayılan olarak etkindir, ancak bunları açıkça etkinleştirmek için, cihaza özel yapılandırmanızda BOARD_DO_NOT_STRIP_VENDOR_RAMDISK_MODULES öğesini cihaz/ vendor / device altında ayarlayın.

Çekirdek ve ramdisk için LZ4 sıkıştırmasını kullanın

Gzip, LZ4'e kıyasla daha küçük bir sıkıştırılmış çıktı üretir, ancak LZ4, Gzip'ten daha hızlı sıkıştırılmış çıktıyı açar. Çekirdek ve modüller için, Gzip kullanımından kaynaklanan mutlak depolama boyutu azalması, LZ4'ün sıkıştırmayı açma süresi avantajıyla karşılaştırıldığında o kadar da önemli değil.

BOARD_RAMDISK_USE_LZ4 aracılığıyla Android platformu derlemesine LZ4 ramdisk sıkıştırma desteği eklendi. Bu seçeneği cihazınıza özel yapılandırmanızda ayarlayabilirsiniz. Çekirdek sıkıştırması çekirdek defconfig aracılığıyla ayarlanabilir.

LZ4'e geçiş, 500 ms ila 1000 ms daha hızlı önyükleme süresi sağlayacaktır.

Sürücülerinizde aşırı oturum açmaktan kaçının

ARM64 ve ARM32'de, çağrı sitesine belirli bir mesafeden daha uzak olan işlev çağrıları, tam atlama adresini kodlayabilmek için bir atlama tablosuna (prosedür bağlantı tablosu veya PLT olarak adlandırılır) ihtiyaç duyar. Modüller dinamik olarak yüklendiğinden bu atlama tablolarının modül yükleme sırasında düzeltilmesi gerekir. Yer değiştirme gerektiren çağrılara, ELF formatında açık eklentiler (veya kısaca RELA) içeren yer değiştirme girişleri adı verilir.

Linux çekirdeği, PLT'yi tahsis ederken bazı bellek boyutu optimizasyonu (önbellek isabet optimizasyonu gibi) yapar. Bu yukarı akış taahhüdü ile optimizasyon şeması bir O(N^2) karmaşıklığına sahiptir; burada N, R_AARCH64_JUMP26 veya R_AARCH64_CALL26 türündeki RELA'ların sayısıdır. Bu nedenle, bu türden daha az sayıda RELA'ya sahip olmak, modül yükleme süresinin azaltılmasına yardımcı olur.

R_AARCH64_CALL26 veya R_AARCH64_JUMP26 RELA'ların sayısını artıran yaygın bir kodlama modeli, sürücüde aşırı oturum açmadır. printk() a veya herhangi başka bir kayıt düzenine yapılan her çağrı genellikle bir CALL26 / JUMP26 RELA girişi ekler. Yukarı akıştaki taahhüt metninde , optimizasyonla bile altı modülün yüklenmesinin yaklaşık 250 ms sürdüğüne dikkat edin; bunun nedeni, bu altı modülün, en fazla günlüğe kaydetme işlemine sahip ilk altı modül olmasıdır.

Günlük kaydının azaltılması, mevcut günlük kaydının ne kadar aşırı olduğuna bağlı olarak önyükleme sürelerinde yaklaşık 100 - 300 ms tasarruf sağlayabilir.

Eşzamansız incelemeyi seçici olarak etkinleştirin

Bir modül yüklendiğinde, desteklediği aygıt zaten DT'den (devicetree) doldurulmuşsa ve sürücü çekirdeğine eklenmişse, aygıt araştırması module_init() çağrısı bağlamında gerçekleştirilir. module_init() bağlamında bir aygıt araştırması yapıldığında, modül, araştırma tamamlanana kadar yüklemeyi bitiremez. Modül yükleme çoğunlukla serileştirilmiş olduğundan, araştırması nispeten uzun süren bir aygıtın önyükleme süresi yavaşlar.

Daha yavaş önyükleme sürelerinden kaçınmak için, cihazlarını araştırması biraz zaman alan modüller için eşzamansız incelemeyi etkinleştirin. Tüm modüller için eşzamansız incelemenin etkinleştirilmesi, bir iş parçacığının çatallanması ve sondanın başlatılması için gereken süre, aygıtın araştırılması için gereken süre kadar yüksek olabileceğinden faydalı olmayabilir.

I2C gibi yavaş bir veri yolu üzerinden bağlanan cihazlar, prob işlevinde bellenim yüklemesi yapan cihazlar ve çok fazla donanım başlatma işlemi yapan cihazlar zamanlama sorununa yol açabilir. Bunun ne zaman olacağını belirlemenin en iyi yolu, her sürücü için araştırma süresini toplamak ve sıralamaktır.

Bir modül için eşzamansız incelemeyi etkinleştirmek için sürücü kodunda yalnızca PROBE_PREFER_ASYNCHRONOUS bayrağını ayarlamak yeterli değildir . Modüller için ayrıca çekirdek komut satırına module_name .async_probe=1 eklemeniz veya modülü modprobe veya insmod kullanarak yüklerken modül parametresi olarak async_probe=1 iletmeniz gerekir.

Eşzamansız incelemenin etkinleştirilmesi, donanımınıza/sürücülerinize bağlı olarak önyükleme sürelerinde yaklaşık 100 - 500 ms tasarruf sağlayabilir.

CPUfreq sürücünüzü mümkün olduğu kadar erken araştırın

CPUfreq sürücünüz ne kadar erken araştırma yaparsa, önyükleme sırasında CPU frekansını o kadar erken maksimuma (veya termal olarak sınırlı bir maksimuma) ölçeklendirebilirsiniz. CPU ne kadar hızlı olursa önyükleme de o kadar hızlı olur. Bu yönerge aynı zamanda DRAM'i, belleği ve ara bağlantı frekansını kontrol eden devfreq sürücüleri için de geçerlidir.

Modüllerde yük sıralaması, sürücülerin initcall düzeyine ve derleme veya bağlantı sırasına bağlı olabilir. cpufreq sürücüsünün yüklenecek ilk birkaç modül arasında olduğundan emin olmak için MODULE_SOFTDEP() takma adını kullanın.

Modülü erken yüklemenin yanı sıra, CPUfreq sürücüsünü araştırmak için tüm bağımlılıkların da araştırıldığından emin olmanız gerekir. Örneğin, CPU'nuzun frekansını kontrol etmek için bir saate veya regülatör koluna ihtiyacınız varsa, önce bunların araştırıldığından emin olun. Veya CPU'larınızın açılış sırasında çok ısınması mümkünse, CPUfreq sürücüsünden önce termal sürücülerin yüklenmesine ihtiyacınız olabilir. Bu nedenle, CPUfreq ve ilgili devfreq sürücülerinin mümkün olduğu kadar erken araştırma yapmasını sağlamak için elinizden geleni yapın.

CPUfreq sürücünüzü erken araştırmaktan elde edeceğiniz tasarruf, bunları ne kadar erken araştırabileceğinize ve önyükleyicinin CPU'ları hangi frekansta bıraktığına bağlı olarak çok küçük ila çok büyük olabilir.

Modülleri ikinci aşama init'e, satıcıya veya satıcı_dlkm bölümüne taşıyın

İlk aşama başlatma işlemi serileştirildiğinden, önyükleme işlemini paralelleştirmek için pek fazla fırsat yoktur. Birinci aşama başlatmanın tamamlanması için bir modüle gerek yoksa, modülü satıcıya veya vendor_dlkm bölümüne yerleştirerek ikinci aşama başlatmaya taşıyın.

Birinci aşama başlatma, ikinci aşama başlatmaya ulaşmak için birden fazla cihazın incelenmesini gerektirmez. Normal bir önyükleme akışı için yalnızca konsol ve flash depolama işlevlerine ihtiyaç vardır.

Aşağıdaki temel sürücüleri yükleyin:

  • bekçi köpeği
  • Sıfırla
  • işlemci frekansı

Kurtarma ve kullanıcı alanı fastbootd modu için, ilk aşama başlatma, araştırmak (USB gibi) ve görüntülemek için daha fazla cihaz gerektirir. Bu modüllerin bir kopyasını ilk aşamadaki ramdisk'te ve satıcı veya vendor_dlkm bölümünde saklayın. Bu, kurtarma veya fastbootd önyükleme akışı için ilk aşamada yüklenmelerine olanak tanır. Ancak normal önyükleme akışı sırasında kurtarma modu modüllerini ilk aşama başlangıcında yüklemeyin. Kurtarma modu modülleri, önyükleme süresini azaltmak için ikinci aşama başlatmaya ertelenebilir. İlk aşamada ihtiyaç duyulmayan tüm diğer modüller, satıcıya veya vendor_dlkm bölümüne taşınmalıdır.

Yaprak aygıtların bir listesi (örneğin, UFS veya seri) verildiğinde dev needs.sh betiği, bağımlılıkların veya tedarikçilerin (örneğin, saatler, düzenleyiciler veya gpio ) araştırılması için gereken tüm sürücüleri, aygıtları ve modülleri bulur.

Modülleri ikinci aşama başlatmaya taşımak, önyükleme sürelerini aşağıdaki şekillerde azaltır:

  • Ramdisk boyutunun küçültülmesi.
    • Bu, önyükleyici ramdiski yüklediğinde (serileştirilmiş önyükleme adımı) daha hızlı flash okuma sağlar.
    • Bu, çekirdek ramdiski sıkıştırdığında (serileştirilmiş önyükleme adımı) daha hızlı açma hızları sağlar.
  • İkinci aşama başlatma paralel olarak çalışır, bu da modülün yükleme süresini ikinci aşama başlatmada yapılan işle gizler.

Modülleri ikinci aşamaya taşımak, başlangıçta ikinci aşamaya kaç modül taşıyabildiğinize bağlı olarak önyükleme sürelerinde 500 - 1000 ms tasarruf sağlayabilir.

Modül yükleme lojistiği

En yeni Android yapısı, her aşamaya hangi modüllerin kopyalanacağını ve hangi modüllerin yükleneceğini kontrol eden kart yapılandırmalarına sahiptir. Bu bölüm aşağıdaki alt kümeye odaklanmaktadır:

  • BOARD_VENDOR_RAMDISK_KERNEL_MODULES . Bu, ramdisk'e kopyalanacak modüllerin listesidir.
  • BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD . Bu ilk aşamada yüklenecek modüllerin listesi.
  • BOARD_VENDOR_RAMDISK_RECOVERY_KERNEL_MODULES_LOAD . Recovery veya fastbootd sırasında yüklenecek modüllerin listesi ramdiskten seçilmektedir.
  • BOARD_VENDOR_KERNEL_MODULES . Bu modül listesi /vendor/lib/modules/ dizinindeki satıcı veya vendor_dlkm bölümüne kopyalanacak.
  • BOARD_VENDOR_KERNEL_MODULES_LOAD . Bu, ikinci aşamada yüklenecek modüllerin listesidir.

Ramdisk'teki önyükleme ve kurtarma modüllerinin de /vendor/lib/modules adresindeki satıcı veya vendor_dlkm bölümüne kopyalanması gerekir. Bu modüllerin satıcı bölümüne kopyalanması, modüllerin ikinci aşama başlatma sırasında görünmez olmasını sağlar; bu, hata ayıklama ve hata raporları için modinfo toplama açısından kullanışlıdır.

Önyükleme modülü seti en aza indirildiği sürece çoğaltma, satıcı veya vendor_dlkm bölümünde minimum alana mal olacaktır. Satıcının modules.list dosyasının /vendor/lib/modules konumunda filtrelenmiş bir modül listesine sahip olduğundan emin olun. Filtrelenen liste, önyükleme sürelerinin modüllerin yeniden yüklenmesinden etkilenmemesini sağlar (bu pahalı bir işlemdir).

Kurtarma modu modüllerinin grup olarak yüklendiğinden emin olun. Kurtarma modu modüllerinin yüklenmesi, kurtarma modunda veya her önyükleme akışındaki ikinci aşamanın başlangıcında yapılabilir.

Aşağıdaki örnekte görüldüğü gibi bu eylemleri gerçekleştirmek için cihazın Board.Config.mk dosyalarını kullanabilirsiniz:

# All kernel modules
KERNEL_MODULES := $(wildcard $(KERNEL_MODULE_DIR)/*.ko)
KERNEL_MODULES_LOAD := $(strip $(shell cat $(KERNEL_MODULE_DIR)/modules.load)

# First stage ramdisk modules
BOOT_KERNEL_MODULES_FILTER := $(foreach m,$(BOOT_KERNEL_MODULES),%/$(m))

# Recovery ramdisk modules
RECOVERY_KERNEL_MODULES_FILTER := $(foreach m,$(RECOVERY_KERNEL_MODULES),%/$(m))
BOARD_VENDOR_RAMDISK_KERNEL_MODULES += \
     $(filter $(BOOT_KERNEL_MODULES_FILTER) \
                $(RECOVERY_KERNEL_MODULES_FILTER),$(KERNEL_MODULES))

# ALL modules land in /vendor/lib/modules so they could be rmmod/insmod'd,
# and modules.list actually limits us to the ones we intend to load.
BOARD_VENDOR_KERNEL_MODULES := $(KERNEL_MODULES)
# To limit /vendor/lib/modules to just the ones loaded, use:
# BOARD_VENDOR_KERNEL_MODULES := $(filter-out \
#     $(BOOT_KERNEL_MODULES_FILTER),$(KERNEL_MODULES))

# Group set of /vendor/lib/modules loading order to recovery modules first,
# then remainder, subtracting both recovery and boot modules which are loaded
# already.
BOARD_VENDOR_KERNEL_MODULES_LOAD := \
        $(filter-out $(BOOT_KERNEL_MODULES_FILTER), \
        $(filter $(RECOVERY_KERNEL_MODULES_FILTER),$(KERNEL_MODULES_LOAD)))
BOARD_VENDOR_KERNEL_MODULES_LOAD += \
        $(filter-out $(BOOT_KERNEL_MODULES_FILTER) \
            $(RECOVERY_KERNEL_MODULES_FILTER),$(KERNEL_MODULES_LOAD))

# NB: Load order governed by modules.load and not by $(BOOT_KERNEL_MODULES)
BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD := \
        $(filter $(BOOT_KERNEL_MODULES_FILTER),$(KERNEL_MODULES_LOAD))

# Group set of /vendor/lib/modules loading order to boot modules first,
# then the remainder of recovery modules.
BOARD_VENDOR_RAMDISK_RECOVERY_KERNEL_MODULES_LOAD := \
    $(filter $(BOOT_KERNEL_MODULES_FILTER),$(KERNEL_MODULES_LOAD))
BOARD_VENDOR_RAMDISK_RECOVERY_KERNEL_MODULES_LOAD += \
    $(filter-out $(BOOT_KERNEL_MODULES_FILTER), \
    $(filter $(RECOVERY_KERNEL_MODULES_FILTER),$(KERNEL_MODULES_LOAD)))

Bu örnek, anakart yapılandırma dosyalarında yerel olarak belirtilecek BOOT_KERNEL_MODULES ve RECOVERY_KERNEL_MODULES yönetimi daha kolay bir alt kümesini gösterir. Önceki komut dosyası, seçilen mevcut çekirdek modüllerindeki alt küme modüllerinin her birini bulur ve doldurur, yeniden inceleme modüllerini ikinci aşama başlatmaya bırakır.

İkinci aşama başlatma için, önyükleme akışını engellememesi için modül yüklemeyi bir hizmet olarak çalıştırmanızı öneririz. Gerekirse hata işleme ve azaltma veya modül yükleme tamamlama gibi diğer lojistik işlemlerinin geri bildirilebilmesi (veya göz ardı edilebilmesi) amacıyla modül yüklemesini yönetmek için bir kabuk komut dosyası kullanın.

Kullanıcı yapılarında bulunmayan bir hata ayıklama modülü yükleme hatasını göz ardı edebilirsiniz. Bu hatayı göz ardı etmek için, vendor.device.modules.ready özelliğini, başlatma ekranına devam etmek üzere init rc komut dosyası oluşturma önyükleme akışının sonraki aşamalarını tetikleyecek şekilde ayarlayın. /vendor/etc/init.insmod.sh dosyasında aşağıdaki kod varsa aşağıdaki örnek komut dosyasına bakın:

#!/vendor/bin/sh
. . .
if [ $# -eq 1 ]; then
  cfg_file=$1
else
  # Set property even if there is no insmod config
  # to unblock early-boot trigger
  setprop vendor.common.modules.ready
  setprop vendor.device.modules.ready
  exit 1
fi

if [ -f $cfg_file ]; then
  while IFS="|" read -r action arg
  do
    case $action in
      "insmod") insmod $arg ;;
      "setprop") setprop $arg 1 ;;
      "enable") echo 1 > $arg ;;
      "modprobe") modprobe -a -d /vendor/lib/modules $arg ;;
     . . .
    esac
  done < $cfg_file
fi

Donanım rc dosyasında one shot hizmet şu şekilde belirtilebilir:

service insmod-sh /vendor/etc/init.insmod.sh /vendor/etc/init.insmod.<hw>.cfg
    class main
    user root
    group root system
    Disabled
    oneshot

Modüller birinci aşamadan ikinci aşamaya geçtikten sonra ek optimizasyonlar yapılabilir. İkinci aşama önyükleme akışını, gerekli olmayan modüllerin ertelenmiş modül yüklemesini içerecek şekilde bölmek için modprobe engelleme listesi özelliğini kullanabilirsiniz. Belirli bir HAL tarafından özel olarak kullanılan modüllerin yüklenmesi, modüllerin yalnızca HAL başlatıldığında yüklenmesi için ertelenebilir.

Görünen önyükleme sürelerini iyileştirmek için, modül yükleme hizmetinde, başlatma ekranından sonra yüklemeye daha yardımcı olan modülleri özel olarak seçebilirsiniz. Örneğin, başlangıç ​​önyükleme akışı temizlendikten sonra video kod çözücü veya wifi modüllerini açık bir şekilde geç yükleyebilirsiniz (örneğin sys.boot_complete Android özellik sinyali). Çekirdek sürücüleri mevcut olmadığında, geç yüklenen modüllere ilişkin HAL'lerin yeterince uzun süre bloke edildiğinden emin olun.

Alternatif olarak, sürücü modüllerinin araştırma işlemlerini tamamladığını göstermek üzere seçilen sysfs girişlerini beklemek için önyükleme akışı rc komut dosyasında init'in wait<file>[<timeout>] komutunu kullanabilirsiniz. Bunun bir örneği, menü grafiklerini sunmadan önce ekran sürücüsünün kurtarma veya fastbootd arka planında yüklemeyi tamamlamasının beklenmesidir.

Önyükleyicide CPU frekansını makul bir değere başlatın

Önyükleme döngüsü testleri sırasındaki termal veya güç sorunları nedeniyle tüm SoC'ler/ürünler CPU'yu en yüksek frekansta başlatamayabilir. Ancak, önyükleyicinin tüm çevrimiçi CPU'ların frekansını bir SoC/ürün için güvenli bir şekilde mümkün olduğu kadar yükseğe ayarladığından emin olun. Bu çok önemlidir çünkü tamamen modüler bir çekirdekte, init ramdisk sıkıştırmasının açılması CPUfreq sürücüsü yüklenmeden önce gerçekleşir. Dolayısıyla, CPU, önyükleyici tarafından frekansının alt ucunda bırakılırsa, ramdisk sıkıştırmasını açma süresi, statik olarak derlenmiş bir çekirdeğe göre daha uzun sürebilir (ramdisk boyutu farkı ayarlandıktan sonra), çünkü CPU yoğun işlem yaparken CPU frekansı çok düşük olacaktır. iş (dekompresyon). Aynı durum bellek/ara bağlantı frekansı için de geçerlidir.

Önyükleyicideki büyük CPU'ların CPU frekansını başlat

CPUfreq sürücüsü yüklenmeden önce çekirdek, küçük ve büyük CPU frekanslarından habersizdir ve CPU'ların planlanan kapasitesini mevcut frekanslarına göre ölçeklendirmez. Küçük CPU üzerindeki yük yeterince yüksekse çekirdek, iş parçacıklarını büyük CPU'ya taşıyabilir.

Büyük CPU'ların, önyükleyicinin onları bıraktığı frekans açısından en az küçük CPU'lar kadar performans gösterdiğinden emin olun. Örneğin, aynı frekans için büyük CPU, küçük CPU'dan 2 kat daha fazla performans gösteriyorsa ancak önyükleyici, önyükleyicinin Küçük CPU'nun frekansı 1,5 GHz'e ve büyük CPU'nun frekansı 300 MHz'e düşerse, çekirdek bir iş parçacığını büyük CPU'ya taşırsa önyükleme performansı düşecektir. Bu örnekte, büyük CPU'yu 750 MHz'de başlatmak güvenliyse, bunu açıkça kullanmayı planlamasanız bile bunu yapmalısınız.

Sürücüler ilk aşamada ürün yazılımını yüklememelidir

Firmware'in ilk aşamada yüklenmesini gerektiren bazı kaçınılmaz durumlar olabilir. Ancak genel olarak sürücüler, özellikle aygıt araştırması bağlamında, ilk aşama başlatmada herhangi bir ürün yazılımı yüklememelidir. Firmware'in ilk aşamada yüklenmesi, firmware'in ilk aşamadaki ramdisk'te mevcut olmaması durumunda tüm önyükleme işleminin durmasına neden olur. Ve ilk aşamadaki ramdiskte bellenim mevcut olsa bile, yine de gereksiz bir gecikmeye neden olur.