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 veyafastbootd
seçildiğinde yüklenir.BOARD_VENDOR_KERNEL_MODULES
. Bu modül listesi,/vendor/lib/modules/
dizinindeki tedarikçiye veyavendor_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.