Açılış süresi optimizasyonu

Bu sayfada, başlatma süresini iyileştirmeye yönelik ipuçları sunulmaktadır.

Modüllerden hata ayıklama sembollerini kaldırma

Üretimde hata ayıklama simgelerinin çekirdekten çıkarılmasına benzer şekilde veya hata ayıklama sembollerini modüllerden çıkardığınızdan emin olun. Hata ayıklama işlemi yapılıyor semboller aşağıdaki değerleri azaltarak başlatma süresine yardımcı olur:

  • İkili dosyaları flash'tan okumak için geçen süre.
  • Ramdisk'in sıkıştırmasını çözmek için geçen süre.
  • Modüllerin yüklenmesi için gereken süre.

Hata ayıklama sembolünün modüllerden çıkarılması başlatma sırasında birkaç saniye kazandırabilir.

Sembol çıkarma özelliği, Android platformu derlemesinde varsayılan olarak etkindir, ancak özel olarak etkinleştirmek için Cihaza özel yapılandırmanızda BOARD_DO_NOT_STRIP_VENDOR_RAMDISK_MODULES altında/vendor/device altında görünür.

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

Gzip, LZ4'e kıyasla daha küçük bir sıkıştırılmış çıkış oluşturur ancak LZ4, Gzip'e kıyasla daha hızlı sıkıştırır. Çekirdek ve modüller için mutlak depolama kullanımından kaynaklanan bir boyut küçültme, 2008'e kıyasla LZ4'ün dekompresyon zamanı açısından faydası.

Android platformuna LZ4 ramdisk sıkıştırması desteği eklendi BOARD_RAMDISK_USE_LZ4 üzerinden geliştiriyoruz. Bu seçeneği, yapılandırdığınızdan emin olun. Çekirdek sıkıştırması, çekirdek defconfig aracılığıyla ayarlanabilir.

LZ4'e geçiş, 500 ila 1.000 ms daha hızlı başlatma süresi sağlar.

Sürücülerinizde aşırı günlük kaydı kullanmaktan kaçının

ARM64 ve ARM32'de, çağrı sitesinden belirli bir mesafeden daha uzaktaki işlev çağrılarının tam atlama adresini kodlayabilmesi için bir atlama tablosuna (prosedür bağlama tablosu veya PLT olarak adlandırılır) ihtiyacı vardır. Modüller dinamik olarak yüklendiğinden bu atlama tablolarının modül yüklemesi sırasında düzeltilmesi gerekir. Taşıma gerektiren çağrılara, ELF biçiminde açık eklemeli (veya kısaca RELA) taşıma girişleri denir.

Linux çekirdeği, PLT'yi ayırırken bazı bellek boyutu optimizasyonları (ör. önbellek isabeti optimizasyonu) yapar. Bu yukarı akış commit ile optimizasyon şemasının karmaşıklığı O(N^2)'dir. 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 RELA'ya sahip olmak modül yükleme süresini azaltmaya yardımcı olur.

R_AARCH64_CALL26 veya R_AARCH64_JUMP26 RELA sayısını artıran yaygın bir kodlama kalıbı, sürücüde aşırı günlük kaydı oluşturmaktır. printk() veya başka bir günlük kaydı şemasına yapılan her çağrı genellikle bir CALL26/JUMP26 RELA girişi ekler. Yukarı akıştaki taahhüt metninde taahhüt, , optimizasyonda bile altı modülün ortalama 250 ms Çünkü bu altı modül, en başarılı altı modüldür. tercih edebilirsiniz.

Günlüğe kaydetme işlemini azaltmak, mevcut günlük kaydetme işleminin ne kadar aşırı olduğuna bağlı olarak açılış sürelerinde yaklaşık 100-300 ms tasarruf sağlayabilir.

Eşzamansız problamayı seçerek etkinleştirme

Bir modül yüklendiğinde, desteklediği cihaz zaten DT'den (devicetree) doldurulup sürücü çekirdeğine eklenir, ardından cihaz durum kontrolü, module_init() çağrısı bağlamında yapılır. module_init() bağlamında bir cihaz araştırması yapıldığında, araştırma tamamlanana kadar modül yüklenemez. Modül yükleme çoğunlukla seri işlem olduğundan, belirlemek nispeten uzun sürer. Bu da başlatma süresini yavaşlatır.

Daha yavaş önyükleme sürelerini önlemek için, cihazlarını taraması biraz zaman alan modüller için eşzamansız tarama özelliğini etkinleştirin. Bir iş parçasını ayırmak ve sondayı başlatmak için gereken süre, cihazı incelemek için gereken süre kadar uzun olabileceğinden, tüm modüller için eşzamansız problamayı etkinleştirmek yararlı olmayabilir.

I2C gibi yavaş bir veri yolu üzerinden bağlanan cihazlar, kontrol işlevinde yüklenen donanım yazılımı ve çok fazla donanım kullanan başlatma işlemi zamanlama sorununa yol açabilir. Bu durumun ne zaman gerçekleştiğini belirlemenin her sürücü için yoklama süresini toplayıp sıralamak.

Bir modül için eşzamansız problamayı etkinleştirmek amacıyla sürücü kodunda yalnızca PROBE_PREFER_ASYNCHRONOUS işaretini ayarlamak yeterli değildir. Modüller için de çekirdek komut satırına module_name.async_probe=1 eklemeniz veya modülü modprobe ya da insmod kullanarak yüklerken async_probe=1'yi modül parametresi olarak iletmeniz gerekir.

Eşzamansız durum kontrolü özelliğinin etkinleştirilmesi, önyükleme sürelerinde yaklaşık 100-500 ms tasarruf sağlayabilir veya sürücülerinize bağlı olarak değişebilir.

CPUfreq sürücünüzü mümkün olduğunca erken kontrol edin

CPUfreq sürücünüz ne kadar erken algılarsa önyükleme sırasında CPU frekansını maksimuma (veya termal olarak sınırlanmış bir maksimuma) o kadar erken ölçeklendirebilirsiniz. CPU ne kadar hızlıysa önyükleme de o kadar hızlı olur. Bu kural devfreq için de geçerlidir DRAM, bellek ve ara bağlantı sıklığını kontrol eden sürücüler

Modüllerde yük sıralaması, initcall seviyesine ve derleme veya bağlantı sıralamasını kontrol edin. MODULE_SOFTDEP() takma adını kullanarak cpufreq sürücüsünün yüklenecek ilk birkaç modül arasında olduğundan emin olun.

Modülü erkenden yüklemenin yanı sıra tüm CPUfreq sürücüsünü araştırmak için duyulan bağımlılıkları da araştırdık. Örneğin, CPU'nuzun frekansını kontrol etmek için bir saat veya düzenleyici koluna ihtiyacınız varsa önce bunların sorgulandığından emin olun. Ayrıca, CPU'larınızın önyükleme sırasında çok ısınması mümkünse termal sürücülerin CPUfreq sürücüsünden önce yüklenmesi gerekebilir. Bu nedenle, CPUfreq ve alakalı yüksek performansın devfreq sürücülerini mümkün olduğunca erken kontrol edin.

CPUfreq sürücünüzü erkenden sorgulayarak elde edeceğiniz tasarruf, bu sürücülerin ne kadar erken sorgulandığına ve önyükleyicinin CPU'ları hangi sıklıkta bıraktığına bağlı olarak çok küçük veya çok büyük olabilir.

Modülleri ikinci aşama init, vendor veya vendor_dlkm bölümüne taşıma

İlk aşama başlatma süreci serileştirilmiş olduğundan çok fazla yoktur daha fazla fırsat sunar. Proje için modüle ihtiyaç duymuyorsanız ilk aşamanın başlatılmasını istiyorsanız, modülü yerleştirerek ikinci aşamaya "Tedarikçi firma veya vendor_dlkm" bölümünde görebilirsiniz.

İlk aşamada başlatma, ikinci aşamada başlatmaya geçmek için birkaç cihazı incelemeyi gerektirmez. Normal bir önyükleme akışı için yalnızca konsol ve flash depolama alanı özellikleri gereklidir.

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

  • watchdog
  • reset
  • cpufreq

Kurtarma ve kullanıcı alanı fastbootd modu için ilk aşama başlatma işlemi daha fazla gerektirir kontrol edilecek (ör. USB) ve gösterilecek. Bu modüllerin bir kopyasını birinci aşama ramdisk'inde ve tedarikçi veya vendor_dlkm bölümünde bulundurun. Bu sayede kurtarma veya fastbootd önyükleme akışı için ilk aşama başlatmada yüklenmelidir. Ancak, normal başlatma sırasında ilk aşamadaki kurtarma modu modüllerini yükleme akışı sağlar. Kurtarma modu modüllerinin kullanılabilmesi için ikinci aşamanın başlatılmasına unutmayın. İlk aşamada ihtiyaç duyulmayan diğer tüm modüller tedarikçi firma veya vendor_dlkm bölümüne taşındı.

Yaprak cihazların listesini (ör. UFS veya seri) belirterek dev needs.sh komut dosyası, bağımlılıklar veya bağımlılıklar için gerekli tüm sürücüleri, cihazları tedarikçilerin (örneğin, saatler, düzenleyiciler veya gpio) kontrol etmesini sağlama.

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

  • Ramdisk boyutu küçültüldü.
    • Bu sayede önyükleme programı ramdisk'i yüklerken (serileştirilmiş önyükleme adımı) daha hızlı flash okumaları elde edilir.
    • Bu sayede çekirdek, ramdisk'i (serileştirilmiş önyükleme adımı) sıkıştırdığında daha hızlı sıkıştırma hızları elde edilir.
  • İkinci aşama başlatma, modülün yükleme süresini gizleyen paralel olarak çalışır işleme daha erken başlar.

Modülleri ikinci aşamaya taşımak, bağlı olarak önyükleme sürelerinde 500-1000 ms tasarruf sağlayabilir kaç modülün başlatılacağına ilişkin bilgi verir.

Modül yükleme lojistiği

En yeni Android derlemesinde, hangi kartları kontrol etmek istediğinizi her aşamaya kopyalanıyor ve hangi modüllerin yüklendiğini görebilirsiniz. Bu bölümde şu alt kümede bulunuyor:

  • BOARD_VENDOR_RAMDISK_KERNEL_MODULES. Bu, ramdisk'e kopyalanacak modüllerin listesidir.
  • BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD Yüklenecek modüllerin listesi ilk aşamadaki değer.
  • BOARD_VENDOR_RAMDISK_RECOVERY_KERNEL_MODULES_LOAD. Bu modül listesi, ramdisk'ten kurtarma veya fastbootd seçildiğinde yüklenir.
  • BOARD_VENDOR_KERNEL_MODULES. Bu modül listesi, /vendor/lib/modules/ dizinindeki tedarikçiye veya vendor_dlkm bölümüne kopyalanacaktır.
  • BOARD_VENDOR_KERNEL_MODULES_LOAD Yüklenecek modüllerin listesi ilk aşamadır.

Ramdisk'teki önyükleme ve kurtarma modülleri de /vendor/lib/modules adresindeki tedarikçiye veya vendor_dlkm bölümüne kopyalanmalıdır. Bu modüller Tedarikçi bölümü, ikinci aşama başlatma sırasında modüllerin görünmez olmasını sağlar. Bu, hata ayıklamada ve hata raporları için modinfo toplama işleminde kullanışlıdır.

Önyükleme modülü grubu en aza indirildiği sürece kopyalama işlemi, tedarikçi veya vendor_dlkm bölümünde çok az yer kaplar. Tedarikçinin modules.list dosyası, /vendor/lib/modules modülünde filtrelenmiş bir modül listesi içeriyor. Filtrelenmiş liste, başlatma sürelerinin modüllerin yüklenmesinden etkilenmemesini sağlar bu pahalı bir işlemdir.

Kurtarma modu modüllerinin grup halinde yüklenmesini sağlayın. Kurtarma modu modüllerini yükleme işlemi, kurtarma modunda veya her önyükleme akışında ikinci aşama init'in başında yapılabilir.

Bu işlemleri gösterildiği gibi gerçekleştirmek için cihazın Board.Config.mk dosyalarını kullanabilirsiniz aşağıdaki örnekte:

# 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 örnekte, kart yapılandırma dosyalarında yerel olarak belirtilecek daha kolay yönetilebilir bir BOOT_KERNEL_MODULES ve RECOVERY_KERNEL_MODULES alt kümesi gösterilmektedir. Yukarıdaki komut dosyası, Google Etiket Yöneticisi'nden alt küme modüllerinin her birini kalan modülleri ikinci sıraya bırakırken, mevcut çekirdek modüllerini sahne başlangıcı.

İkinci aşama başlatma için modülü bir hizmet olarak çalıştırmanızı öneririz. önyükleme akışını engellemez. Modül yüklemeyi yönetmek için bir kabuk komut dosyası kullanın Böylece hata giderme ve azaltma ya da modül yükü gibi diğer lojistik gerektiğinde geri bildirilebilir (veya göz ardı edilebilir).

Kullanıcı derlemelerinde bulunmayan bir hata ayıklama modülü yükleme hatasını yoksayabilirsiniz. Bu hatayı yoksaymak için vendor.device.modules.ready özelliğini, başlatma ekranına devam etmek için init rc komut dosyası önyükleme akışının sonraki aşamalarını tetikleyecek şekilde ayarlayın. /vendor/etc/init.insmod.sh dosyasında aşağıdaki koda sahipseniz 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 hizmeti şunlarla 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 ilk modülden sonraki modüle taşındıktan sonra ek optimizasyonlar oluşturuyoruz. Modprobe engellenenler listesi özelliğini kullanarak ikinci aşama önyükleme akışını, gerekli olmayan modüllerin ertelenen modül yüklemesini içerecek şekilde bölebilirsiniz. Yalnızca belirli bir HAL tarafından kullanılan modüllerin yüklenmesi ertelenebilir seçeneğini belirleyin.

Görünen önyükleme sürelerini iyileştirmek için Google Play'deki lansmandan sonra yüklemeye daha elverişli olan modül yükleme hizmetleri tıklayın. Örneğin, başlatma akışı temizlendikten sonra video kod çözücü veya kablosuz bağlantı (sys.boot_complete) Örneğin, Android mülkü sinyali). Geç yükleme için HAL'lerin geçerli olduğundan emin olun modüller, çekirdek sürücüleri olmadığında yeterince uzun bir süre bloke edilir.

Alternatif olarak, sürücü modüllerinin tarama işlemlerini tamamladığını gösteren belirli sysfs girişlerini beklemek için önyükleme akışı rc komut dosyasında init'in wait<file>[<timeout>] komutunu kullanabilirsiniz. Bunun bir örneği, kurtarma sırasında arka planda yüklemeyi tamamlamak için sürücüyü görüntüleyin veya fastbootd, menü grafiklerini sunmadan önce.

CPU frekansını bootloader'da makul bir değere başlatın

Tüm SoC'ler/ürünler CPU'yu en yüksek frekansta başlatamayabilir test sırasında ısınma veya güçle ilgili sorunlara neden olabilir. Ancak bootloader tüm çevrimiçi CPU'ların sıklığını güvenli olduğu kadar yüksek bir değere ayarlar soC için mümkün olmayabilir. Bu çok önemlidir çünkü init ramdisk açma işlemi, CPUfreq'ten önce gerçekleştiği için yüklenmesi gerekir. Bu durumda, CPU, frekansının alt ucunda kalırsa yüklenince, ramdisk sıkıştırma açma süresi bir statik olarak derlenmiş çekirdek (ramdisk boyutu farkı için ayarlandıktan sonra) Çünkü CPU'yu yoğun bir şekilde çalıştırırken CPU frekansı çok düşük olur (sıkıştırma). Aynı durum bellek ve ara bağlantı sıklığı için de geçerlidir.

Bootloader'daki büyük CPU'ların CPU frekansını başlatın

CPUfreq sürücüsü yüklenmeden önce çekirdek, CPU frekanslarından haberdar değildir ve CPU planlama kapasitesini mevcut frekanslarına göre ölçeklendirmez. Küçük CPU'da 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ığı frekansta en az küçük CPU'lar kadar performanslı olduğundan emin olun. Örneğin, büyük CPU aynı frekans için küçük CPU'lardan 2 kat daha iyi performans gösterir, ancak bootloader küçük CPU'nun frekansını 1,5 GHz olarak ayarlar ve büyük CPU'nun frekansı 300 MHz'e çıkarırsanız çekirdek bir ileti dizisini büyük CPU'ya taşır. Bu örnekte, büyük ihtimalle başlatmanın CPU 750 MHz'deyse, açıkça kullanmayı düşünmeseniz bile bunu kullanmalısınız.

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

Donanım yazılımının ilk aşamada başlatılması gereken bazı kaçınılmaz durumlar olabilir. Ancak genel olarak sürücüler, özellikle cihaz probu bağlamında ilk aşamada herhangi bir donanım yazılımı yüklememelidir. Donanım yazılımı, ilk aşama init'e yüklenirken ilk aşama ramdisk'te mevcut değilse tüm önyükleme işleminin duraklamasına neden olur. Donanım yazılımı ilk aşamada mevcut olsa bile ramdisk, yine de gereksiz bir gecikmeye neden olur.