Bu sayfada, başlatma süresini iyileştirmeye yönelik ipuçları verilmektedir.
Modüllerden hata ayıklama sembollerini kaldırma
Hata ayıklama sembollerinin üretim cihazındaki çekirdekten kaldırılmasına benzer şekilde, hata ayıklama sembollerini modüllerden de kaldırdığınızdan emin olun. Hata ayıklama sembollerinin modüllerden kaldırılması, aşağıdakileri azaltarak başlatma süresini kısaltır:
- İkili dosyaların flash'tan okunması için geçen süre.
- Ramdisk'in sıkıştırmasının açılması için gereken süre.
- Modüllerin yüklenmesi için gereken süre.
Hata ayıklama simgesinin modüllerden kaldırılması, önyükleme sırasında birkaç saniye kazandırabilir.
Sembol kaldırma, Android platform derlemesinde varsayılan olarak etkindir ancak bunları açıkça etkinleştirmek için cihazınıza özel yapılandırmanızda device/vendor/device altında BOARD_DO_NOT_STRIP_VENDOR_RAMDISK_MODULES
değerini ayarlayın.
Çekirdek ve ramdisk için LZ4 sıkıştırmasını kullanma
Gzip, LZ4'e kıyasla daha küçük bir sıkıştırılmış çıktı oluşturur ancak LZ4, Gzip'ten daha hızlı açılır. Çekirdek ve modüller için Gzip kullanıldığında elde edilen mutlak depolama alanı boyutu azalması, LZ4'ün sıkıştırmayı açma süresi avantajına kıyasla o kadar da önemli değildir.
Android platformu derlemesine BOARD_RAMDISK_USE_LZ4
aracılığıyla LZ4 ramdisk sıkıştırma desteği eklendi. Bu seçeneği cihaza özel yapılandırmanızda ayarlayabilirsiniz. Çekirdek sıkıştırma, kernel defconfig aracılığıyla ayarlanabilir.
LZ4'e geçiş, 500 ms ila 1.000 ms daha hızlı başlatma süresi sağlayacaktır.
Sürücülerinizde aşırı günlük kaydı oluşturmaktan kaçının
ARM64 ve ARM32'de, çağrı sitesinden belirli bir mesafeden daha uzak olan işlev çağrıları, tam atlama adresini kodlayabilmek için bir atlama tablosu (prosedür bağlama tablosu veya PLT olarak adlandırılır) gerektirir. Modüller dinamik olarak yüklendiğinden bu atlama tablolarının modül yükleme sırasında düzeltilmesi gerekir. Yeniden konumlandırılması gereken çağrılara, ELF biçiminde açık eklenenli yeniden konumlandırma girişleri (veya kısaca RELA) adı verilir.
Linux çekirdeği, PLT'yi ayırırken bellek boyutu optimizasyonu (ör. önbellek isabeti optimizasyonu) yapar. Bu yukarı akışlı
commit ile optimizasyon şeması O(N^2)
karmaşıklığına sahiptir. Burada N
, R_AARCH64_JUMP26
veya R_AARCH64_CALL26
türündeki RLA'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'ların sayısını artıran yaygın bir kodlama kalıbı, sürücüdeki aşırı günlük kaydıdı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. commit text in the upstream
commit (yukarı akış commit'indeki commit metni) bölümünde,
optimizasyon yapılmasına rağmen altı modülün yüklenmesinin yaklaşık 250 ms sürdüğünü
görürsünüz. Bunun nedeni, bu altı modülün en fazla günlük kaydı içeren ilk altı modül olmasıdır.
Günlük kaydını azaltmak, mevcut günlük kaydının ne kadar fazla olduğuna bağlı olarak başlatma sürelerinde yaklaşık 100-300 ms tasarruf sağlayabilir.
Eşzamansız yoklamayı seçici olarak etkinleştirme
Bir modül yüklendiğinde, desteklediği cihaz zaten DT'den (devicetree) doldurulmuş ve sürücü çekirdeğine eklenmişse cihaz yoklama işlemi 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ün yüklenmesi tamamlanamaz. Modül yükleme işlemi çoğunlukla seri olarak yapıldığından, yoklama işlemi nispeten uzun süren bir cihaz, başlatma süresini yavaşlatır.
Daha yavaş başlatma sürelerini önlemek için cihazlarını yoklaması biraz zaman alan modüller için eşzamansız yoklamayı etkinleştirin. Tüm modüller için eşzamansız yoklamanın etkinleştirilmesi, bir iş parçacığını çatallayıp yoklamayı başlatmak için gereken süre cihazı yoklamak için gereken süre kadar uzun olabileceğinden faydalı olmayabilir.
I2C gibi yavaş bir veri yolu üzerinden bağlanan cihazlar, prob işlevlerinde donanım yazılımı yükleme işlemi yapan cihazlar ve çok fazla donanım başlatma işlemi yapan cihazlar zamanlama sorununa yol açabilir. Bunun ne zaman gerçekleştiğini belirlemenin en iyi yolu, her sürücünün yoklama süresini toplayıp sıralamaktır.
Bir modül için eşzamansız yoklamayı etkinleştirmek üzere yalnızca sürücü kodunda PROBE_PREFER_ASYNCHRONOUS
işaretini ayarlamak yeterli değildir. Modüller için çekirdek komut satırına module_name.async_probe=1
eklemeniz veya modprobe
ya da insmod
kullanarak modülü yüklerken async_probe=1
değerini modül parametresi olarak iletmeniz gerekir.
Asenkron yoklamayı etkinleştirmek, donanımınıza/sürücünüze bağlı olarak başlatma sürelerinde yaklaşık 100-500 ms tasarruf sağlayabilir.
CPUfreq sürücünüzü mümkün olduğunca erken yoklayın
CPUfreq sürücünüz ne kadar erken yoklama yaparsa önyükleme sırasında CPU frekansını en yüksek değere (veya termal olarak sınırlı bir maksimum değere) o kadar erken ölçeklendirebilirsiniz. CPU ne kadar hızlıysa başlatma da o kadar hızlı olur. Bu yönerge, devfreq
DRAM, bellek ve ara bağlantı frekansını kontrol eden sürücüler için de geçerlidir.
Modüllerde yükleme sırası, initcall
düzeyine ve sürücülerin derleme veya bağlantı sırasına bağlı olabilir. MODULE_SOFTDEP()
sürücüsünün yüklenen ilk birkaç modül arasında olmasını sağlamak için cpufreq
diğer adını kullanın.
Modülü erken yüklemenin yanı sıra, CPUfreq sürücüsünü yoklamak için gereken tüm bağımlılıkların da yoklandığından emin olmanız gerekir. Örneğin, CPU'nuzun frekansını kontrol etmek için bir saat veya regülatör kolu gerekiyorsa bunların önce araştırıldığından emin olun. Ayrıca, işlemcilerinizin başlatma sırasında aşırı ısınması mümkünse CPUfreq sürücüsünden önce termal sürücülerin yüklenmesi gerekebilir. Bu nedenle, CPUfreq ve ilgili devfreq sürücülerinin mümkün olduğunca erken araştırma yapmasını sağlamak için elinizden geleni yapın.
CPUfreq sürücünüzü erken yoklamanın sağlayacağı tasarruf, bunları ne kadar erken yoklayabileceğinize 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 başlatma, tedarikçi veya tedarikçi_dlkm bölümüne taşıma
İlk aşamadaki başlatma süreci sıralı olduğundan başlatma sürecini paralelleştirmek için çok fazla fırsat yoktur. Bir modülün ilk aşama başlatma işleminin tamamlanması için gerekmiyorsa modülü tedarikçi veya vendor_dlkm
bölümüne yerleştirerek ikinci aşama başlatma işlemine taşıyın.
İlk aşama başlatma, ikinci aşama başlatmaya ulaşmak için birden fazla cihazın incelenmesini gerektirmez. Normal bir başlatma akışı için yalnızca konsol ve flash depolama özellikleri gerekir.
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, daha fazla cihazın (ör. USB) ve ekranın yoklanmasını gerektirir. Bu modüllerin bir kopyasını ilk aşama ramdisk'te ve vendor veya vendor_dlkm
bölümünde saklayın. Bu sayede, kurtarma veya fastbootd
başlatma akışı için ilk aşamada başlatılabilirler. Ancak normal başlatma akışı sırasında ilk aşama başlatma işleminde kurtarma modu modüllerini yüklemeyin. Kurtarma modu modülleri, başlatma süresini kısaltmak için ikinci aşama başlatmaya ertelenebilir. İlk aşamada başlatma için gerekli olmayan diğer tüm modüller, tedarikçi veya vendor_dlkm
bölümüne taşınmalıdır.
Yaprak cihazların listesi (ör. UFS veya seri) verildiğinde,
dev needs.sh
komut dosyası, bağımlılıklar veya tedarikçiler (ör. saatler, regülatörler veya gpio
) için gereken tüm sürücüleri, cihazları ve modülleri bulur.
Modüllerin ikinci aşama başlatmaya taşınması, aşağıdaki şekillerde başlatma sürelerini kısaltır:
- Ramdisk boyutu küçültüldü.
- Bu, önyükleyici ramdisk'i yüklediğinde (serileştirilmiş önyükleme adımı) daha hızlı flash okumaları sağlar.
- Bu, çekirdek ramdisk'i (serileştirilmiş önyükleme adımı) açarken daha hızlı açma hızları sağlar.
- İkinci aşama başlatma işlemi paralel olarak çalışır. Bu sayede, ikinci aşama başlatma işleminde yapılan çalışmayla modülün yükleme süresi gizlenir.
Modülleri ikinci aşamaya taşıdığınızda, ikinci aşama başlatmaya kaç modül taşıyabildiğinize bağlı olarak 500-1000 ms arasında başlatma süresi tasarrufu sağlayabilirsiniz.
Modül yükleme lojistiği
En yeni Android derlemesinde, hangi modüllerin her aşamaya kopyalanacağını ve hangi modüllerin yükleneceğini kontrol eden kart yapılandırmaları bulunur. Bu bölümde aşağıdaki alt kümeye odaklanılmaktadır:
BOARD_VENDOR_RAMDISK_KERNEL_MODULES
. Bu, ramdisk'e kopyalanacak modüllerin listesidir.BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD
. Bu, ilk aşama başlatma sırasında yüklenecek modüllerin listesidir.BOARD_VENDOR_RAMDISK_RECOVERY_KERNEL_MODULES_LOAD
. Bu, ramdisk'ten kurtarma veyafastbootd
seçildiğinde yüklenecek modüllerin listesidir.BOARD_VENDOR_KERNEL_MODULES
. Bu modüllerin listesi,/vendor/lib/modules/
dizinindekivendor_dlkm
bölümüne kopyalanır.BOARD_VENDOR_KERNEL_MODULES_LOAD
. Bu, ikinci aşama başlatma sırasında yüklenecek modüllerin listesidir.
Ramdisk'teki başlatma ve kurtarma modülleri de /vendor/lib/modules
bölümündeki vendor veya vendor_dlkm
bölümüne kopyalanmalıdır. Bu modüllerin satıcı bölümüne kopyalanması, modüllerin ikinci aşama başlatma sırasında görünmez olmamasını sağlar. Bu, hata ayıklama ve hata raporları için modinfo
toplama açısından faydalıdır.
Yineleme, önyükleme modülü grubu en aza indirildiği sürece satıcıda veya vendor_dlkm
bölümünde
minimum alan kaplamalıdır. Tedarikçinin modules.list
dosyasında, /vendor/lib/modules
içinde filtrelenmiş bir modül listesi olduğundan emin olun.
Filtrelenmiş liste, başlatma sürelerinin modüllerin tekrar yüklenmesinden (pahalı bir işlem) etkilenmemesini sağlar.
Kurtarma modu modüllerinin grup olarak yüklendiğinden emin olun. Kurtarma modu modüllerinin yüklenmesi, kurtarma modunda veya her başlatma akışında ikinci aşama başlatma işleminin başında yapılabilir.
Aşağıdaki örnekte gösterildiği gibi bu işlemleri gerçekleştirmek için cihaz 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 örnekte, kart yapılandırma dosyalarında yerel olarak belirtilecek BOOT_KERNEL_MODULES
ve RECOVERY_KERNEL_MODULES
öğelerinin yönetimi daha kolay olan bir alt kümesi gösterilmektedir. Yukarıdaki komut dosyası, seçilen kullanılabilir çekirdek modüllerinden her bir alt küme modülünü bulup doldurur ve kalan modülleri ikinci aşama başlatma için bırakır.
İkinci aşama başlatma için modül yüklemeyi hizmet olarak çalıştırmanızı öneririz. Böylece, başlatma akışı engellenmez. Modül yüklemeyi yönetmek için bir kabuk komut dosyası kullanın. Böylece, hata işleme ve azaltma veya modül yükleme işleminin tamamlanması gibi diğer lojistikler gerekirse bildirilebilir (veya yoksayılabilir).
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 ayarlayın. Bu, init rc
komut dosyası başlatma akışının sonraki aşamalarını tetikleyerek başlatma ekranına geçilmesini sağlar. Aşağıdaki koda sahipseniz /vendor/etc/init.insmod.sh
aşağıdaki örnek komut dosyasını inceleyin:
#!/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 ş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 başlatma akışını, gerekli olmayan modüllerin ertelenmiş modül yüklemesini içerecek şekilde bölmek için modprobe engelleme listesi özelliğini kullanabilirsiniz. Yalnızca belirli bir HAL tarafından kullanılan modüllerin yüklenmesi, modüllerin yalnızca HAL başlatıldığında yüklenmesi için ertelenebilir.
Görünür önyükleme sürelerini iyileştirmek için özellikle başlatma ekranından sonra yüklemeye daha uygun olan modül yükleme hizmetindeki modülleri seçebilirsiniz. Örneğin, başlatma önyükleme akışı temizlendikten sonra (sys.boot_complete
örneğin Android mülk sinyali) video kod çözücü veya kablosuz modüllerini açıkça geç yükleyebilirsiniz. Geç yüklenen modüllerin HAL'lerinin, çekirdek sürücüleri mevcut olmadığında yeterince uzun süre engellediğinden emin olun.
Alternatif olarak, sürücü modüllerinin yoklama işlemlerini tamamladığını göstermek için belirli sysfs
girişlerinin görünmesini beklemek üzere başlatma akışı rc komut dosyalarında init'in wait<file>[<timeout>]
komutunu kullanabilirsiniz. Buna örnek olarak, menü grafiklerini göstermeden önce kurtarma işleminin arka planında ekran sürücüsünün yüklenmesinin tamamlanmasını bekleme veya fastbootd
verilebilir.
CPU frekansını bootloader'da makul bir değere başlatın.
Önyükleme döngüsü testleri sırasında termal veya güç sorunları nedeniyle tüm SoC'ler/ürünler CPU'yu en yüksek frekansta başlatamayabilir. Ancak önyükleyicinin, SoC veya ürün için güvenli bir şekilde mümkün olduğunca yüksek bir frekans belirlediğinden emin olun. Tamamen modüler bir çekirdekte init ramdisk sıkıştırması, CPUfreq sürücüsü yüklenebilmeden önce gerçekleştiği için bu çok önemlidir. Bu nedenle, önyükleyici tarafından frekansının alt ucunda bırakılan işlemcinin ramdisk sıkıştırmasını açma süresi, statik olarak derlenmiş bir çekirdeğe göre (ramdisk boyutu farkı ayarlandıktan sonra) daha uzun sürebilir. Bunun nedeni, işlemci yoğun işler (sıkıştırmayı açma) yapılırken işlemci frekansının çok düşük olmasıdır. Aynı durum bellek ve ara bağlantı sıklığı için de geçerlidir.
Bootloader'da büyük CPU'ların CPU frekansını başlatma
CPUfreq
sürücüsü yüklenmeden önce çekirdek, CPU frekanslarının farkında değildir ve CPU planlama kapasitesini mevcut frekanslarına göre ölçeklendirmez. Yük, küçük CPU'da yeterince yüksekse çekirdek, iş parçacıklarını büyük CPU'ya taşıyabilir.
Büyük CPU'ların, önyükleyici tarafından bırakıldıkları frekansta küçük CPU'lar kadar performanslı olduğundan emin olun. Örneğin, büyük CPU aynı frekansta küçük CPU'dan 2 kat daha iyi performans gösteriyorsa ancak önyükleyici küçük CPU'nun frekansını 1, 5 GHz, büyük CPU'nun frekansını ise 300 MHz olarak ayarlıyorsa çekirdek bir iş parçacığını büyük CPU'ya taşıdığında başlatma performansı düşer. Bu örnekte, büyük CPU'yu 750 MHz'de başlatmak güvenliyse açıkça kullanmayı planlamasanız bile bunu yapmanız gerekir.
Sürücüler, ilk aşama başlatma sırasında donanım yazılımı yüklememelidir.
Donanım yazılımının ilk aşama başlatma sırasında yüklenmesi gereken bazı kaçınılmaz durumlar olabilir. Ancak genel olarak sürücüler, özellikle cihaz yoklama bağlamında ilk aşama başlatma sırasında herhangi bir donanım yazılımı yüklememelidir. İlk aşama başlatma sırasında donanım yazılımının yüklenmesi, donanım yazılımı ilk aşama ramdisk'inde mevcut değilse tüm başlatma sürecinin durmasına neden olur. Donanım yazılımı ilk aşama ramdisk'te bulunsa bile gereksiz bir gecikmeye neden olur.