欢迎光临
专业Linux运维二十年

Linux 启动时间优化实战,2.41 秒启动应用!

劳动节快乐,祝大家都能有所收获!

今天我参加了一个关于启动优化的讲座,这里简要总结一下。

本文旨在分享一些简单有效的优化方法,并不涵盖所有技巧。有兴趣的朋友可以关注我的视频号,后续我会通过直播与大家进一步交流。

目标系统

硬件:

Beagle Bone Black (Cortex A8)

USB 摄像头 + LCD

软件:

Linux 5.1 + Buildroot rootfs

FFmpeg,用于采集视频并解码到 LCD。

点击查看大图

当前启动时间:

从上电到 LCD 显示第一帧图像:9.45 秒

1、优化编译器ARM vs Thumb2

比较基于 ARM 或 Thumb2 指令集编译的系统和应用。

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

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

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

尽管性能有所提升,我个人还是倾向于选择 ARM 指令集。

musl vs uClibc

Buildroot 中有三种 C 库可选:glibc、musl、uClibc,我们只比较后两种较小的库。

musl:680 KB (统计 /lib 目录)。

uClibc:570 KB (-16%)。

uClibc 节省了 110 KB,我们选择 uClibc。

2、优化应用程序我们可以通过 ./configure 对 FFmpeg 的功能组件进行选择。

此外,还可以使用 strace 和 perf 命令调试以优化 FFmpeg 的内部代码。

优化后的结果:

文件系统:从 16.11 MB 缩小到 3.54 MB (-78%)。

程序的加载和运行时间:缩短 150 ms。

整体启动时间:缩短 350 ms。

虽然空间优化效果显著,但在启动时间上的优化较小,这是因为 Linux 在运行程序时只加载程序的必要部分。

3、优化 Init 和根文件系统思路:

使用 bootchartd 分析系统启动并裁剪不必要的服务。

将 /etc/init.d/ 下的启动脚本合并为一个。

不挂载 /proc 和 /sys。

裁剪 BusyBox,文件系统越小,内核挂载可能会越快。

将 Init 程序替换为我们的应用程序。

静态编译应用程序。

裁剪掉不常用的文件,找出长时间不访问的文件:

优化后的结果:

文件系统:裁剪 Busybox 后,从 3.54 MB 缩小到 2.33 MB (-34%)。

启动时间:基本没有变化,大概是因为文件系统本身已经足够小了。

使用 initramfs 作为 rootfs:

通常情况下,Linux 系统会先挂载 initramfs,initramfs 很小且位于内存中,再由 initramfs 负责负载根文件系统。

当我们将 Buildroot rootfs 裁剪得很小时,就可以考虑直接将其作为 initramfs 使用。

这样有什么好处呢?

initramfs 可以和 Kernel 拼接在一起,Bootloader 负责将 Kernel+initramfs 加载到内存中,内核不再需要访问磁盘。

内核不再需要 block/storage 和 filesystem 相关的功能,体积会变得更小,加载时间和初始化时间都会变小。

注意,需要关闭 initramfs 的压缩(CONFIG_INITRAMFS_COMPRESSION_NONE)。

优化后的结果:

即便禁用了 CONFIG_BLOCK 和 CONFIG_MMC 后,总启动时间仍增加了 20ms。这可能是因为 Kernel + initramfs 拼在一起之后,内核变大了许多,而内核镜像是需要解压,解压的时间增多了。

4、优化内核评估方法:

在启动参数中添加 initcall_debug,可以获得更多内核 log:

此外,可以使用 scripts/bootgraph.pl 将 dmesg 的信息转换成图片:

点击查看大图

接下来,找出消耗时间最多的环节,进行优化。

裁掉 tracing

在 Kernel hacking 中关闭 Tracers 相关的功能。

启动时间:缩短 550ms。

内核大小:缩小 217KB。

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

预设 loops per jiffy

在每次启动时,内核都会校准 delay loop 的值,用于 udelay() 函数。

这会测量 loops per jiffy (lpj) 的值。我们只需要启动一次内核,在 log 中查找 lpj 值:

然后将 lpj=4980736 填写到启动参数中,即可:

大约缩短了 82 ms。

禁用 CONFIG_SMP

SMP 的初始化很慢。它通常在默认配置中是启用的,即使是一个单核 CPU。

如果我们的平台是单核的,可以禁用 SMP。

关闭后,内核缩小:-188 KB (-4.6%),启动时间缩短 126ms.

禁用 log

启动参数中添加 quiet,启动时间缩短 577 ms。

禁用 CONFIG_PRINTK 和 CONFIG_BUG 后,内核缩小 118 KB (-5.8%)。

禁用 CONFIG_KALLSYMS 后,内核缩小 107 KB (-5.7%)。

合计,启动时间缩短 767 ms。

开启 CONFIG_EMBEDDED 和 CONFIG_EXPERT

这会让系统调用变得更精简,内核会变得没那么通用,但是能保持你的应用程序能运行就足够了。

内核缩小 51 KB。

启动时间缩短 34 ms。

选择 SLAB memory allocators

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

SLAB:默认选择,最通用、最传统、最可靠。

SLOB:更简洁,代码量更少,更节省空间,适合嵌入式系统,使能后,内核缩小 5 KB,但是启动时间增加 1.43 S!

SLUB:更合适大型系统,使能后,启动时间增加 2 ms。

因此,我们仍使用 SLAB。

内核压缩方式

不同压缩方式的特点如下:

实测效果:

看起来,gzip 和 lzo 表现更好。测试的效果应该是和 CPU/磁盘 的性能相关的。

内核编译参数

使能 CONFIG_CC_OPTIMIZE_FOR_SIZE,该选项可能是用 gcc -Os 代替 gcc -O2。

点击查看大图

注意,这只是在 BeagleBone Black + Linux 5.1 上的测试结果,不同平台之间有差异。

禁用 /proc 等伪文件系统

要考虑应用的兼容性。

ffmpeg 依赖 /proc,所以只能关闭一些 proc 相关的选项:CONFIG_PROC_SYSCTL、CONFIG_PROC_PAGE_MONITOR CONFIG_CONFIGFS_FS,启动时间没有变化。

关闭 sysfs,启动时间缩短 35 ms。

拼接 DTB

启用 CONFIG_ARM_APPENDED_DTB:

启动时间缩短 26 ms。

5、优化 Bootloader这里我们采用最好的方案:使用 Uboot Falcon mode。

Falcon mode 只执行 Uboot 的第一阶段:SPL,然后跳过 Stage 2,执行加载 Kernel。

启动时间缩短 250 ms。

总结到此,启动优化基本完成,最终效果如下:

从上电到 LCD 显示第一帧图像,总时间为 2.41 秒。

最有效果的步骤如下:

点击查看大图

仍值得优化的空间:

系统花了 1.2 秒等待 USB 摄像头的枚举,这里是否有办法加速?

是否可以关闭 tty 和终端登录?

最后,关于优化启动时间,有一些原则可以遵循:

请不要过早地进行优化。

从一些影响面最小的点开始优化。

从 rootfs、kernel、bootloader 自上而下进行优化。

重点关注短板。

感谢阅读,欢迎转发哦!

以上就是Linux 启动时间优化实战,2.41 秒启动应用!的详细内容,更多请关注php中文网其它相关文章!

脚本之家
赞(0) 打赏
未经允许不得转载:Linux老运维 » Linux 启动时间优化实战,2.41 秒启动应用!

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续提供更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫

微信扫一扫