<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Linux 啟動(dòng)時(shí)間優(yōu)化實(shí)戰(zhàn),2.41 秒啟動(dòng)應(yīng)用!

          共 4441字,需瀏覽 9分鐘

           ·

          2022-05-15 23:27

          來(lái)源于:老吳嵌入式

          今天看了一個(gè)關(guān)于啟動(dòng)優(yōu)化的講座,簡(jiǎn)單總結(jié)一下。

          本文的目標(biāo)是嘗試一些比較簡(jiǎn)單有效的方法,并不會(huì)覆蓋所有的優(yōu)化技巧。


          目標(biāo)系統(tǒng)

          硬件:

          Beagle Bone Black (Cortex A8)

          USB 攝像頭 + LCD

          軟件

          Linux 5.1 + Buildroot rootfs

          FFmpeg,用于采集視頻并解碼到 LCD。

          點(diǎn)擊查看大圖

          當(dāng)前啟動(dòng)時(shí)間

          從上電到 LCD 顯示第一幀圖像:9.45 秒


          1、優(yōu)化編譯器

          ARM vs Thumb2

          比較基于 ARM 或者 Thumb2 指令集編譯出來(lái)的系統(tǒng)和應(yīng)用。

          ARM:rootfs 為 3.79 MB,ffmpeg 為 227 KB。

          Thumb2:3.10 MB (-18 %),183 KB (-19 %)。

          性能方面:Thumb2 的性能明顯略有提升 (約小于 5 %)。

          雖然性能有所提升,但是我個(gè)人還是會(huì)選擇 ARM 指令集。

          musl vs uClibc

          Buildroot 里有 3 種 C庫(kù)可以選擇:glibc、musl、uClibc,這里我們只比較后面 2 種比較小巧的庫(kù)。

          musl:680 KB (統(tǒng)計(jì) /lib 目錄)。

          uClibc:570 KB (-16 %)。

          uClibc 節(jié)省了 110 KB,我們選擇 uClibc。

          2、優(yōu)化應(yīng)用程序

          我們可以通過(guò) ./configure 對(duì) FFmpeg 的功能組件進(jìn)行選擇。

          另外,還可以用 strace 和 perf 命令調(diào)試以優(yōu)化 FFmpeg 的內(nèi)部d代碼。

          優(yōu)化后的結(jié)果:

          文件系統(tǒng):從 16.11 MB 縮小到 3.54 MB (-78 %)。

          程序的加載和運(yùn)行時(shí)間:縮短 150 ms。

          整體啟動(dòng)時(shí)間:縮短 350 ms。

          在空間的優(yōu)化很大,但是在啟動(dòng)時(shí)間上的優(yōu)化很小,這是因?yàn)?Linux 運(yùn)行程序時(shí)只加載程序的必要部分。


          3、優(yōu)化 Init 和根文件系統(tǒng)

          思路:

          使用 bootchartd 分析系統(tǒng)啟動(dòng)并裁剪不必要的服務(wù)。

          將 /etc/init.d/ 下的啟動(dòng)腳本合并為一個(gè)。

          不掛載 /proc 和 /sys。

          裁剪 BusyBox,文件系統(tǒng)越小,內(nèi)核掛載可能會(huì)越快。

          將 Init 程序替換成我們的應(yīng)用程序。

          靜態(tài)編譯應(yīng)用程序。

          裁剪掉不常用的文件,找出長(zhǎng)時(shí)間不訪問(wèn)的文件:

          $?find?/?-atime?-1000?-type?f

          優(yōu)化后的結(jié)果:

          文件系統(tǒng):裁剪 Busybox 后,從 3.54 MB 縮小到 2.33 MB (-34 %)。

          啟動(dòng)時(shí)間:基本沒(méi)改變,大概是因?yàn)槲募到y(tǒng)本身就足夠小了。

          使用 initramfs 作為 rootfs:

          一般情況下,Linux 系統(tǒng)會(huì)先掛載 initramfs,init ramfs 很小且位于內(nèi)存中,再由 initramfs 負(fù)責(zé)負(fù)載根文件系統(tǒng)。

          當(dāng)我們將 Buildroot rootfs 裁剪得很小時(shí),就可以考慮直接將其作為 initramfs 使用。

          這樣有什么好處呢?

          initramfs 可以和 Kernel 拼接在一起,Bootloader 負(fù)責(zé)將 Kernel+initramfs 加載到內(nèi)存中,內(nèi)核不再需要訪問(wèn)磁盤(pán)。

          內(nèi)核不再需要 block/storage 和 filesystem 相關(guān)的功能,體積會(huì)變得更小,加載時(shí)間和初始化時(shí)間都會(huì)變小。

          注意,需要關(guān)閉 initramfs 的壓縮(CONFIG_INITRAMFS_COMPRESSION_NONE)。

          優(yōu)化后的結(jié)果:

          即便禁用了 CONFIG_BLOCK 和 CONFIG_MMC 后,總啟動(dòng)時(shí)間仍多了 20ms。這可能是因?yàn)?Kernel + initramfs 拼在一起之后,內(nèi)核變大了許多,而內(nèi)核鏡像是需要解壓,解壓的時(shí)間增多了。

          4、優(yōu)化內(nèi)核

          評(píng)估方法:

          在啟動(dòng)參數(shù)里添加 initcall_debug,能得到更多內(nèi)核 log:

          [?3.750000]?calling?ov2640_i2c_driver_init+0x0/0x10?@?1
          [?3.760000]?initcall?ov2640_i2c_driver_init+0x0/0x10?returned?0?after?544?usecs
          [?3.760000]?calling?at91sam9x5_video_init+0x0/0x14?@?1
          [?3.760000]?at91sam9x5-video?f0030340.lcdheo1:?video?device?registered?@?0xe0d3e340,?irq?=?24
          [?3.770000]?initcall?at91sam9x5_video_init+0x0/0x14?returned?0?after?10388?usecs
          [?3.770000]?calling?gspca_init+0x0/0x18?@?1
          [?3.770000]?gspca_main:?v2.14.0?registered
          [?3.770000]?initcall?gspca_init+0x0/0x18?returned?0?after?3966?usecs
          ...

          另外,可以用 scripts/bootgraph.pl 將 dmesg 的信息轉(zhuǎn)換成圖片:

          $?scripts/bootgraph.pl?boot.log?>?boot.svg

          點(diǎn)擊查看大圖

          接下來(lái),找出消耗時(shí)間最多的環(huán)節(jié),進(jìn)行優(yōu)化。

          裁掉 tracing

          在 Kernel hacking 里關(guān)閉 Tracers 相關(guān)的功能。

          啟動(dòng)時(shí)間:縮短 550ms。

          內(nèi)核大小:縮小 217KB。

          裁掉一些用不上的硬件功能

          omap8250_platform_driver_init()?//?(660?ms)
          cpsw_driver_init()??//?(112?ms)
          am335x_child_init()?//?(82?ms)
          ...

          預(yù)設(shè) loops per jiffy

          在每次啟動(dòng)時(shí),內(nèi)核都會(huì)校準(zhǔn) delay loop 的值,用于 udelay() 函數(shù)。

          這會(huì)測(cè)量 loops per jiffy (lpj) 的值。我們只需要啟動(dòng)一次內(nèi)核,在log 查找 lpj 值:

          Calibrating?delay?loop...?996.14?BogoMIPS?(lpj=4980736)

          然后將 lpj=4980736 填寫(xiě)到啟動(dòng)參數(shù)中,即可:

          Calibrating?delay?loop?(skipped)?preset?value..?996.14?BogoMIPS?(lpj=4980736)

          大約縮短了 82 ms。

          禁用 CONFIG_SMP

          SMP 的初始化很慢。它通常在默認(rèn)配置中是啟用的,即使是一個(gè)單核 CPU。

          如果我們的平臺(tái)是單核的,可以禁用 SMP。

          關(guān)閉后,內(nèi)核縮小:-188 KB (-4.6 %),啟動(dòng)時(shí)間縮短 126ms.

          禁用 log

          啟動(dòng)參數(shù)里添加 quiet,啟動(dòng)時(shí)間縮短 577 ms。

          禁用 CONFIG_PRINTK 和 CONFIG_BUG 后,內(nèi)核縮小 118 KB (-5.8 %) 。

          禁用 CONFIG_KALLSYMS 后,內(nèi)核縮小 107 KB (-5.7 %) 。

          合計(jì),啟動(dòng)時(shí)間縮短 767 ms。

          開(kāi)啟 CONFIG_EMBEDDED 和 CONFIG_EXPERT

          這會(huì)讓系統(tǒng)調(diào)用變得更精簡(jiǎn),內(nèi)核會(huì)變得沒(méi)那么通用,但是能保持你的應(yīng)用程序能運(yùn)行就足夠了。

          內(nèi)核縮小 51 KB。

          啟動(dòng)時(shí)間縮短 34 ms。

          選擇 SLAB memory allocators

          一般是 SLAB、SLOB、SLUB 三選一。

          SLAB:默認(rèn)選擇,最通用、最傳統(tǒng)、最可靠。

          SLOB:更簡(jiǎn)潔,代碼量更少,更節(jié)省空間,適合嵌入式系統(tǒng),使能后,內(nèi)核縮小 5 KB,但是啟動(dòng)時(shí)間增加 1.43 S!

          SLUB:更合適大型系統(tǒng),使能后,啟動(dòng)時(shí)間增加 2 ms。

          因此,我們?nèi)允褂?SLAB。

          內(nèi)核壓縮方式

          不同壓縮方式的特點(diǎn)如下:

          實(shí)測(cè)效果:

          看起來(lái),gzip 和 lzo 表現(xiàn)更好。測(cè)試的效果應(yīng)該是和 CPU/磁盤(pán) 的性能相關(guān)的。

          內(nèi)核編譯參數(shù)

          使能 CONFIG_CC_OPTIMIZE_FOR_SIZE,該選項(xiàng)可能是用 gcc -Os 代替 gcc -O2。

          點(diǎn)擊查看大圖

          注意,這只是在 BeagleBone Black + Linux 5.1 上的測(cè)試結(jié)果,不同平臺(tái)之間有差異。

          禁用 /proc 等偽文件系統(tǒng)

          要考慮應(yīng)用的兼容性。

          ffmpeg 依賴 /proc ,所以只能關(guān)閉一些 proc 相關(guān)的選項(xiàng):CONFIG_PROC_SYSCTL、CONFIG_PROC_PAGE_MONITOR CONFIG_CONFIGFS_FS,啟動(dòng)時(shí)間沒(méi)有變化。

          關(guān)閉 sysfs, 啟動(dòng)時(shí)間縮短 35 ms。

          拼接 DTB

          啟用 CONFIG_ARM_APPENDED_DTB:

          $?cat?arch/arm/boot/zImage?arch/arm/boot/dts/am335x-boneblack-lcd4.dtb?>?zImage

          $?setenv?bootcmd?'fatload?mmc?0:1?81000000?zImage;?bootz?81000000'

          啟動(dòng)時(shí)間縮短 26 ms。

          5、優(yōu)化 Bootloader

          這里我們采用最好的方案:使用 Uboot Falcon mode。

          Falcon mode 只執(zhí)行 Uboot 的第一階段:SPL,然后跳過(guò) Stage 2,執(zhí)行加載 Kernel。

          啟動(dòng)時(shí)間縮短 250 ms。

          總結(jié)

          到此,啟動(dòng)優(yōu)化基本完成,最終效果如下:

          [0.000000?0.000000]
          [0.000785?0.000785]?U-Boot?SPL?2019.01?(Oct?27?2019?-?08:04:06?+0100)
          [0.057822?0.057822]?Trying?to?boot?from?MMC1
          [0.378878?0.321056]?fdt_root:?FDT_ERR_BADMAGIC
          [0.775306?0.396428]?Waiting?for?/dev/video0?to?be?ready...
          [1.966367?1.191061]?Starting?ffmpeg
          ...
          [2.412284?0.004277]?First?frame?decoded

          從上電到 LCD 顯示第一幀圖像,總時(shí)間為 2.41 秒。

          最有效果的步驟如下

          點(diǎn)擊查看大圖

          仍值得優(yōu)化的空間

          系統(tǒng)花了 1.2 秒等待 USB 攝像頭的枚舉,這里是否有辦法加速?

          是否可以關(guān)閉 tty 和終端登錄?

          最后,關(guān)于優(yōu)化啟動(dòng)時(shí)間,有一些原則可以遵循

          請(qǐng)不要過(guò)早地進(jìn)行優(yōu)化。

          從一些影響面最小的點(diǎn)開(kāi)始優(yōu)化。

          從 rootfs 、kernel、bootloader 自上而下進(jìn)行優(yōu)化。

          重點(diǎn)關(guān)注短板。

          Linux學(xué)習(xí)指南

          有收獲,點(diǎn)個(gè)在看?

          瀏覽 26
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲精品水蜜桃 | 制服丝袜看操逼网站 | 国产成人三级视频 | 日日操天天 | 天天激情站|