原文:https://source.android.com/devices/tech/perf/boot-times
本文檔提供了有關(guān)改進(jìn)特定 Android 設(shè)備的啟動(dòng)時(shí)間的合作伙伴指南。啟動(dòng)時(shí)間是系統(tǒng)性能的重要組成部分,因?yàn)橛脩舯仨毜却龁?dòng)完成后才能使用設(shè)備辑舷。對(duì)于較常進(jìn)行冷啟動(dòng)的汽車等設(shè)備而言滓玖,較短的啟動(dòng)時(shí)間至關(guān)重要(沒(méi)有人喜歡在等待幾十秒后才能輸入導(dǎo)航目的地)歪脏。
Android 8.0 支持一系列組件的多項(xiàng)改進(jìn)弟劲,以縮短啟動(dòng)時(shí)間绩聘。下表對(duì)這些性能改進(jìn)(在 Google Pixel 和 Pixel XL 設(shè)備上測(cè)得)進(jìn)行了總結(jié)。
組件 | 改進(jìn) |
---|---|
引導(dǎo)加載程序 | * 通過(guò)移除 UART 日志節(jié)省了 1.6 秒盲憎; * 通過(guò)從 GZIP 更改為 LZ4 節(jié)省了 0.4 秒 |
設(shè)備內(nèi)核 | * 通過(guò)移除不使用的內(nèi)核配置和減少驅(qū)動(dòng)程序大小節(jié)省了 0.3 秒; * 通過(guò) dm-verity 預(yù)提取優(yōu)化節(jié)省了 0.3 秒胳挎; * 通過(guò)移除驅(qū)動(dòng)程序中不必要的等待/測(cè)試饼疙,節(jié)省了 0.15 秒; * 通過(guò)移除 CONFIG_CC_OPTIMIZE_FOR_SIZE慕爬,節(jié)省了 0.12 秒 |
I/O 調(diào)整 | * 正常啟動(dòng)時(shí)間節(jié)省了 2 秒窑眯; * 首次啟動(dòng)時(shí)間節(jié)省了 25 秒; |
init.*.rc | * 通過(guò)并行運(yùn)行 init 命令節(jié)省了 1.5 秒医窿; * 通過(guò)及早啟動(dòng) zygote 節(jié)省了 0.25 秒伸但; * 通過(guò) cpuset 調(diào)整節(jié)省了 0.22 秒 |
啟動(dòng)動(dòng)畫(huà) | * 在未觸發(fā) fsck 的情況下,啟動(dòng)動(dòng)畫(huà)的開(kāi)始時(shí)間提前了 2 秒留搔,而觸發(fā) fsck 時(shí)啟動(dòng)動(dòng)畫(huà)則大得多更胖; * 通過(guò)立即關(guān)閉啟動(dòng)動(dòng)畫(huà)在 Pixel XL 上節(jié)省了 5 秒 |
SELinux 政策 | 通過(guò) genfscon 節(jié)省了 0.2 秒 |
優(yōu)化引導(dǎo)加載程序
要優(yōu)化引導(dǎo)加載程序以縮短啟動(dòng)時(shí)間,請(qǐng)遵循以下做法:
- 對(duì)于日志記錄:
- 停止向 UART 寫(xiě)入日志隔显,因?yàn)槿绻罩居涗浐芏嗳捶粒瑒t可能需要很長(zhǎng)時(shí)間來(lái)處理。(在 Google Pixel 設(shè)備上括眠,我們發(fā)現(xiàn)這會(huì)使引導(dǎo)加載程序的速度減慢 1.5 秒)彪标。
- 僅記錄錯(cuò)誤情況,并考慮將其他信息存儲(chǔ)到具有單獨(dú)檢索機(jī)制的內(nèi)存中掷豺。
- 對(duì)于內(nèi)核解壓縮捞烟,請(qǐng)考慮為當(dāng)代硬件使用 LZ4 而非 GZIP(例如補(bǔ)丁程序)薄声。請(qǐng)注意,不同的內(nèi)核壓縮選項(xiàng)具有不同的加載和解壓縮時(shí)間题画,對(duì)于特定硬件默辨,某些選項(xiàng)可能比其他選項(xiàng)更適合。
- 檢查進(jìn)入去抖動(dòng)/特殊模式過(guò)程中是否有不必要的等待時(shí)間苍息,并最大限度地減少此類時(shí)間缩幸。
- 將在引導(dǎo)加載程序中花費(fèi)的啟動(dòng)時(shí)間以命令行的形式傳遞到內(nèi)核。
- 檢查 CPU 時(shí)鐘并考慮內(nèi)核加載和初始化 I/O 并行進(jìn)行(需要多核支持)竞思。
優(yōu)化內(nèi)核
請(qǐng)按照以下提示優(yōu)化內(nèi)核以縮短啟動(dòng)時(shí)間表谊。
最大限度地減少設(shè)備 defconfig
最大限度地減少內(nèi)核配置可以減小內(nèi)核大小,從而更快速地進(jìn)行加載盖喷、解壓縮爆办、初始化并縮小受攻擊面。要優(yōu)化設(shè)備 defconfig课梳,請(qǐng)執(zhí)行以下操作:
-
識(shí)別未使用的驅(qū)動(dòng)程序押逼。查看
/dev
和/sys
目錄,并查找?guī)в谐R?guī) SELinux 標(biāo)簽的節(jié)點(diǎn)(這種標(biāo)簽表示相應(yīng)節(jié)點(diǎn)未配置為可由用戶空間訪問(wèn))惦界。如果找到此類節(jié)點(diǎn)挑格,請(qǐng)將其移除。 - 取消設(shè)置未使用的配置沾歪。查看由內(nèi)核版本生成的 .config 文件漂彤,以明確取消設(shè)置所有已默認(rèn)啟用但并未使用的配置。例如灾搏,我們從 Google Pixel 中移除了以下未使用的配置:
CONFIG_ANDROID_LOGGER=y
CONFIG_IMX134=y
CONFIG_IMX132=y
CONFIG_OV9724=y
CONFIG_OV5648=y
CONFIG_GC0339=y
CONFIG_OV8825=y
CONFIG_OV8865=y
CONFIG_s5k4e1=y
CONFIG_OV12830=y
CONFIG_USB_EHCI_HCD=y
CONFIG_IOMMU_IO_PGTABLE_FAST_SELFTEST=y
CONFIG_IKCONFIG=y
CONFIG_RD_BZIP2=y
CONFIG_RD_LZMA=y
CONFIG_TI_DRV2667=y
CONFIG_CHR_DEV_SCH=y
CONFIG_MMC=y
CONFIG_MMC_PERF_PROFILING=y
CONFIG_MMC_CLKGATE=y
CONFIG_MMC_PARANOID_SD_INIT=y
CONFIG_MMC_BLOCK_MINORS=32 CONFIG_MMC_TEST=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_SDHCI_MSM=y
CONFIG_MMC_SDHCI_MSM_ICE=y
CONFIG_MMC_CQ_HCI=y
CONFIG_MSDOS_FS=y
# CONFIG_SYSFS_SYSCALL is not set
CONFIG_EEPROM_AT24=y
# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
CONFIG_INPUT_HBTP_INPUT=y
# CONFIG_VGA_ARB is not set
CONFIG_USB_MON=y
CONFIG_USB_STORAGE_DATAFAB=y
CONFIG_USB_STORAGE_FREECOM=y
CONFIG_USB_STORAGE_ISD200=y
CONFIG_USB_STORAGE_USBAT=y
CONFIG_USB_STORAGE_SDDR09=y
CONFIG_USB_STORAGE_SDDR55=y
CONFIG_USB_STORAGE_JUMPSHOT=y
CONFIG_USB_STORAGE_ALAUDA=y
CONFIG_USB_STORAGE_KARMA=y
CONFIG_USB_STORAGE_CYPRESS_ATACB=y
CONFIG_SW_SYNC_USER=y
CONFIG_SEEMP_CORE=y
CONFIG_MSM_SMEM_LOGGING=y
CONFIG_IOMMU_DEBUG=y
CONFIG_IOMMU_DEBUG_TRACKING=y
CONFIG_IOMMU_TESTS=y
CONFIG_MOBICORE_DRIVER=y
# CONFIG_DEBUG_PREEMPT is not set
- 移除導(dǎo)致每次啟動(dòng)時(shí)運(yùn)行不必要測(cè)試的配置挫望。雖然此類配置(如 CONFIG_IOMMU_IO_PGTABLE_FAST_SELFTEST)在開(kāi)發(fā)過(guò)程中很有用,但應(yīng)從正式版內(nèi)核中移除狂窑。
最大限度地減小驅(qū)動(dòng)程序大小
如果未使用相應(yīng)功能媳板,則可以移除設(shè)備內(nèi)核中的某些驅(qū)動(dòng)程序,以便進(jìn)一步減小內(nèi)核大小泉哈。例如蛉幸,如果 WLAN 通過(guò) PCIe 連接,則不會(huì)用到 SDIO 支持丛晦,因此應(yīng)在編譯時(shí)將其移除诱贿。有關(guān)詳情老虫,請(qǐng)參閱 Google Pixel 內(nèi)核:網(wǎng)絡(luò):無(wú)線:CNSS:添加選項(xiàng)以停用 SDIO 支持延刘。
移除針對(duì)大小的編譯器優(yōu)化
移除 CONFIG_CC_OPTIMIZE_FOR_SIZE 的內(nèi)核配置魂那。此標(biāo)記是在最初假設(shè)較小的代碼大小會(huì)產(chǎn)生熱緩存命中(因此速度更快)時(shí)引入的。然而锌蓄,隨著現(xiàn)代移動(dòng) SoC 變得更加強(qiáng)大升筏,這一假設(shè)不再成立撑柔。
此外,移除此標(biāo)記可以使編譯器針對(duì)未初始化的變量發(fā)出警告您访,當(dāng)存在 CONFIG_CC_OPTIMIZE_FOR_SIZE 標(biāo)記時(shí)铅忿,這一功能在 Linux 內(nèi)核中是停用的(僅這一項(xiàng)更改就已幫助我們?cè)谀承?Android 設(shè)備驅(qū)動(dòng)程序中發(fā)現(xiàn)了很多有意義的錯(cuò)誤)。
延遲初始化
很多進(jìn)程都在設(shè)備啟動(dòng)期間啟動(dòng)洋只,但只有關(guān)鍵路徑 (bootloader > kernel > init > file system mount > zygote > system server) 中的組件才會(huì)直接影響啟動(dòng)時(shí)間。在內(nèi)核啟動(dòng)期間執(zhí)行 initcall 來(lái)識(shí)別啟動(dòng)速度緩慢且對(duì)啟動(dòng) init 進(jìn)程不重要的外設(shè)/組件昼捍,然后通過(guò)將這些外設(shè)/組件移入可加載的內(nèi)核模塊將其延遲到啟動(dòng)過(guò)程的后期來(lái)啟動(dòng)识虚。移入異步設(shè)備/驅(qū)動(dòng)程序探測(cè)還有助于并行啟動(dòng)內(nèi)核 > init 重要路徑中啟動(dòng)速度緩慢的組件。
BoardConfig-common.mk:
BOARD_KERNEL_CMDLINE += initcall_debug ignore_loglevel
driver:
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
注:必須添加
EPROBEDEFER
支持來(lái)妥善解決驅(qū)動(dòng)程序依賴問(wèn)題妒茬。
優(yōu)化 I/O 效率
提高 I/O 效率對(duì)縮短啟動(dòng)時(shí)間來(lái)說(shuō)至關(guān)重要担锤,對(duì)任何不必要內(nèi)容的讀取都應(yīng)推遲到啟動(dòng)之后再進(jìn)行(在 Google Pixel 上,啟動(dòng)時(shí)大約要讀取 1.2GB 的數(shù)據(jù))乍钻。
調(diào)整文件系統(tǒng)
當(dāng)從頭開(kāi)始讀取某個(gè)文件或依序讀取塊時(shí)肛循,預(yù)讀的 Linux 內(nèi)核便會(huì)啟動(dòng),這就需要調(diào)整專門(mén)用于啟動(dòng)的 I/O 調(diào)度程序參數(shù)(與普通應(yīng)用的工作負(fù)載特性不同)银择。
支持無(wú)縫 (A/B) 更新的設(shè)備在首次啟動(dòng)時(shí)會(huì)極大地受益于文件系統(tǒng)調(diào)整(例如多糠,Google Pixel 的啟動(dòng)時(shí)間縮短了 20 秒)。例如浩考,我們?yōu)?Google Pixel 調(diào)整了以下參數(shù):
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
...
其他
- 使用內(nèi)核配置 DM_VERITY_HASH_PREFETCH_MIN_SIZE(默認(rèn)大小為 128)來(lái)啟用 dm-verity 哈希預(yù)提取大小夹孔。
- 為了提升文件系統(tǒng)穩(wěn)定性及取消每次啟動(dòng)時(shí)的強(qiáng)制檢查,請(qǐng)?jiān)?BoardConfig.mk 中設(shè)置 TARGET_USES_MKE2FS析孽,以使用新的 ext4 生成工具搭伤。
分析 I/O
要了解啟動(dòng)過(guò)程中的 I/O 活動(dòng),請(qǐng)使用內(nèi)核 ftrace 數(shù)據(jù)(systrace 也使用該數(shù)據(jù)):
trace_event=block,ext4 in BOARD_KERNEL_CMDLINE
要針對(duì)每個(gè)文件細(xì)分文件訪問(wèn)權(quán)限袜瞬,請(qǐng)對(duì)內(nèi)核進(jìn)行以下更改(僅限開(kāi)發(fā)版內(nèi)核怜俐;請(qǐng)勿在正式版內(nèi)核中應(yīng)用這些更改):
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);
使用以下腳本來(lái)幫助分析啟動(dòng)性能。
-
system/extras/boottime_tools/bootanalyze/bootanalyze.py
:負(fù)責(zé)衡量啟動(dòng)時(shí)間邓尤,并詳細(xì)分析啟動(dòng)過(guò)程中的重要步驟拍鲤。 -
system/extras/boottime_tools/io_analysis/check_file_read.py boot_trace
:提供每個(gè)文件的訪問(wèn)信息。 -
system/extras/boottime_tools/io_analysis/check_io_trace_all.py boot_trace
:提供系統(tǒng)級(jí)細(xì)分信息汞扎。
優(yōu)化 init.*.rc
Init 是從內(nèi)核到框架建立之前的銜接過(guò)程殿漠,設(shè)備通常會(huì)在不同的 init 階段花費(fèi)幾秒鐘時(shí)間。
并行運(yùn)行任務(wù)
雖然當(dāng)前的 Android init 差不多算是一種單線程進(jìn)程佩捞,但您仍然可以并行執(zhí)行一些任務(wù)绞幌。
- 在 Shell 腳本服務(wù)中執(zhí)行緩慢命令,然后通過(guò)等待特定屬性一忱,在稍后加入莲蜘。Android 8.0 通過(guò)新的
wait_for_property
命令支持此用例谭确。 - 識(shí)別 init 中的緩慢操作。系統(tǒng)會(huì)記錄 init 命令 exec/wait_for_prop 或任何所需時(shí)間較長(zhǎng)的操作(在 Android 8.0 中票渠,指所需時(shí)間超過(guò) 50 毫秒的任何命令)逐哈。例如:
init: Command 'wait_for_coldboot_done' action=wait_for_coldboot_done returned 0 took 585.012ms
查看此日志可能會(huì)發(fā)現(xiàn)可以改進(jìn)的機(jī)會(huì)。
- 啟動(dòng)服務(wù)并及早啟用關(guān)鍵路徑中的外圍設(shè)備问顷。例如昂秃,有些 SOC 需要先啟動(dòng)安全相關(guān)服務(wù),然后再啟動(dòng) SurfaceFlinger杜窄。在 ServiceManager 返回“wait for service”(等待服務(wù))時(shí)查看系統(tǒng)日志 - 這通常表明必須先啟動(dòng)依賴服務(wù)肠骆。
- 移除 init.*.rc 中所有未使用的服務(wù)和命令。只要是早期階段的 init 中沒(méi)有使用的服務(wù)和命令塞耕,都應(yīng)推遲到啟動(dòng)完成后再使用蚀腿。
注:“屬性”服務(wù)是 init 進(jìn)程的一部分,因此扫外,在啟動(dòng)期間調(diào)用
setproperty
可能會(huì)導(dǎo)致較長(zhǎng)時(shí)間的延遲(如果 init 忙于執(zhí)行內(nèi)置命令)莉钙。
使用調(diào)度程序調(diào)整
使用調(diào)度程序調(diào)整,以便及早啟動(dòng)設(shè)備筛谚。以下是取自 Google Pixel 的示例:
on init
# update cpusets now that processors are up
write /dev/cpuset/top-app/cpus 0-3
write /dev/cpuset/foreground/cpus 0-3
write /dev/cpuset/foreground/boost/cpus 0-3
write /dev/cpuset/background/cpus 0-3
write /dev/cpuset/system-background/cpus 0-3
# set default schedTune value for foreground/top-app (only affects EAS)
write /dev/stune/foreground/schedtune.prefer_idle 1
write /dev/stune/top-app/schedtune.boost 10
write /dev/stune/top-app/schedtune.prefer_idle 1
部分服務(wù)在啟動(dòng)過(guò)程中可能需要進(jìn)行優(yōu)先級(jí)提升磁玉。例如:
init.zygote64.rc:
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
class main
priority -20
user root
...
及早啟動(dòng) zygote
采用文件級(jí)加密的設(shè)備可以在 zygote-start 觸發(fā)器的早期階段啟動(dòng) zygote(默認(rèn)情況下,zygote 會(huì)在 main 類中啟動(dòng)驾讲,比 zygote-start 晚得多)蜀涨。這樣做時(shí),請(qǐng)確保允許 zygote 在所有 CPU 中運(yùn)行(因?yàn)殄e(cuò)誤的 cpuset 設(shè)置可能會(huì)強(qiáng)制 zygote 在特定 CPU 中運(yùn)行)蝎毡。
停用節(jié)電設(shè)置
在設(shè)備啟動(dòng)期間厚柳,可以停用 UFS 和/或 CPU 調(diào)節(jié)器等組件的節(jié)電設(shè)置。
請(qǐng)注意:為了提高效率沐兵,應(yīng)在充電器模式下啟用節(jié)電設(shè)置别垮。
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
推遲非關(guān)鍵初始化
非關(guān)鍵初始化(如 ZRAM)可以推遲到 boot_complete。
on property:sys.boot_completed=1
# Enable ZRAM on boot_complete
swapon_all /vendor/etc/fstab.${ro.hardware}
優(yōu)化啟動(dòng)動(dòng)畫(huà)
請(qǐng)按照以下提示來(lái)優(yōu)化啟動(dòng)動(dòng)畫(huà)扎谎。
配置為及早啟動(dòng)
Android 8.0 支持在裝載用戶數(shù)據(jù)分區(qū)之前碳想,及早啟動(dòng)動(dòng)畫(huà)。然而毁靶,即使 Android 8.0 中使用了新的 ext4 工具鏈胧奔,系統(tǒng)也會(huì)出于安全原因定期觸發(fā) fsck,導(dǎo)致啟動(dòng) bootanimation 服務(wù)時(shí)出現(xiàn)延遲预吆。
為了使 bootanimation 及早啟動(dòng)龙填,請(qǐng)將 fstab 裝載分為以下兩個(gè)階段:
- 在早期階段,僅裝載不需要運(yùn)行檢查的分區(qū)(例如
system/
和vendor/
),然后啟動(dòng)啟動(dòng)動(dòng)畫(huà)服務(wù)及其依賴項(xiàng)(例如 servicemanager 和 surfaceflinger)岩遗。 - 在第二個(gè)階段扇商,裝載需要運(yùn)行檢查的分區(qū)(例如
data/
)。
啟動(dòng)動(dòng)畫(huà)將會(huì)更快速地啟動(dòng)(且啟動(dòng)時(shí)間恒定)宿礁,不受 fsck 影響案铺。
干凈利落地結(jié)束
在收到退出信號(hào)后,bootanimation 會(huì)播放最后一部分梆靖,而這一部分的長(zhǎng)度會(huì)延長(zhǎng)啟動(dòng)時(shí)間控汉。快速啟動(dòng)的系統(tǒng)不需要很長(zhǎng)的動(dòng)畫(huà)返吻,如果啟動(dòng)動(dòng)畫(huà)很長(zhǎng)姑子,在很大程度上就體現(xiàn)不出所做的任何改進(jìn)。我們建議縮短循環(huán)播放和結(jié)尾的時(shí)間思喊。
優(yōu)化 SELinux
請(qǐng)按照以下提示優(yōu)化 SELinux 以縮短啟動(dòng)時(shí)間壁酬。
-
使用簡(jiǎn)潔的正則表達(dá)式 (regex)次酌。在為
file_contexts
中的sys/devices
匹配 SELinux 政策時(shí)恨课,格式糟糕的正則表達(dá)式可能會(huì)導(dǎo)致大量開(kāi)銷。例如岳服,正則表達(dá)式/sys/devices/.*abc.*(/.*)?
錯(cuò)誤地強(qiáng)制掃描包含“abc”的所有/sys/devices
子目錄剂公,導(dǎo)致/sys/devices/abc
和/sys/devices/xyz/abc
都成為匹配項(xiàng)。如果將此正則表達(dá)式修正為/sys/devices/[^/]*abc[^/]*(/.*)?
吊宋,則只有/sys/devices/abc
會(huì)成為匹配項(xiàng)纲辽。 - **將標(biāo)簽移動(dòng)到 **genfscon。這一現(xiàn)有的 SELinux 功能會(huì)將文件匹配前綴傳遞到 SELinux 二進(jìn)制文件的內(nèi)核中璃搜,而內(nèi)核會(huì)將這些前綴應(yīng)用于內(nèi)核生成的文件系統(tǒng)拖吼。這也有助于修復(fù)錯(cuò)誤標(biāo)記的內(nèi)核創(chuàng)建的文件,從而防止用戶空間進(jìn)程之間可能出現(xiàn)的爭(zhēng)用情況(試圖在重新標(biāo)記之前訪問(wèn)這些文件)这吻。
工具和方法
請(qǐng)使用以下工具來(lái)幫助您收集用于優(yōu)化目標(biāo)的數(shù)據(jù)吊档。
bootchart
bootchart 可為整個(gè)系統(tǒng)提供所有進(jìn)程的 CPU 和 I/O 負(fù)載細(xì)分。該工具不需要重建系統(tǒng)映像唾糯,可以用作進(jìn)入 systrace 之前的快速健全性檢查怠硼。
要啟用 bootchart,請(qǐng)運(yùn)行以下命令:
$ adb shell 'touch /data/bootchart/enabled'
$ adb reboot
在設(shè)備啟動(dòng)后移怯,獲取啟動(dòng)圖表:
$ ANDROID_BUILD_TOP/system/core/init/grab-bootchart.sh
完成后香璃,請(qǐng)刪除 /data/bootchart/enabled
以防止每次都收集日期數(shù)據(jù)。
systrace
systrace 允許在啟動(dòng)期間收集內(nèi)核和 Android 跟蹤記錄舟误。 systrace 的可視化可以幫助分析啟動(dòng)過(guò)程中的具體問(wèn)題葡秒。(不過(guò),要查看整個(gè)啟動(dòng)過(guò)程中的平均數(shù)量或累計(jì)數(shù)量,直接查看內(nèi)核跟蹤記錄更為方便)同云。
要在啟動(dòng)過(guò)程中啟用 systrace糖权,請(qǐng)執(zhí)行以下操作:
- 在
frameworks/native/atrace/atrace.rc
中,將
write /sys/kernel/debug/tracing/tracing_on 0
更改為:
#write /sys/kernel/debug/tracing/tracing_on 0
這將啟用跟蹤功能(默認(rèn)處于停用狀態(tài))炸站。
- 在
device.mk
文件中星澳,添加下面這行內(nèi)容:
PRODUCT_PROPERTY_OVERRIDES += debug.atrace.tags.enableflags=802922
- 在設(shè)備
BoardConfig.mk
文件中,添加以下內(nèi)容:
BOARD_KERNEL_CMDLINE := ... trace_buf_size=64M trace_event=sched_wakeup,sched_switch,sched_blocked_reason,sched_cpu_hotplug
要獲得詳細(xì)的 I/O 分析旱易,還需要添加塊和 ext4禁偎。
- 在設(shè)備專用的
init.rc
文件中,進(jìn)行以下更改:-
on property:sys.boot_completed=1
(這會(huì)在啟動(dòng)完成后停止跟蹤) write /d/tracing/tracing_on 0
write /d/tracing/events/ext4/enable 0
write /d/tracing/events/block/enable 0
-
在設(shè)備啟動(dòng)后阀坏,獲取跟蹤記錄:
$ adb root && adb shell "cat /d/tracing/trace" < boot_trace
./external/chromium-trace/catapult/tracing/bin/trace2html boot_trace --output boot_trace.html
注意:Chrome 無(wú)法處理過(guò)大的文件如暖。請(qǐng)考慮使用
tail
、head
或grep
分割boot_trace
文件忌堂,以獲得必要的部分盒至。由于事件過(guò)多,I/O 分析通常需要直接分析獲取的boot_trace
士修。