跳转到内容
来自 Arch Linux 中文维基

提升系统的启动性能可以缩短启动等待时长,还能学习系统文件和脚本见交互的方式。本文整合了数种提升 Arch Linux 启动性能的方式。

启动过程分析

使用 systemd-analyze

systemd 提供了一个名为 systemd-analyze 的工具,可用于显示有关启动过程的计时细节, 包括一个显示各单元等待其依赖项的 svg 图。您可以看到哪些单元文件导致启动过程减慢, 然后可以相应地优化系统.

要查看启动时在内核/用户空间中消耗的时间, 只需使用:

$ systemd-analyze
提示:如果系统使用 UEFI 引导,且启动引导器实现了 systemd 的启动引导器接口(目前只有 GRUBsystemd-boot 实现了),systemd-analyze 还可以显示 EFI 固件和启动引导器自身花费的时间。

按照耗费时间顺序,列出启动各个单元耗费的时间:

$ systemd-analyze blame

在启动过程的一些时刻,需要特定的单元成功启动了才能继续。要查看在启动链中哪些单元处于这些关键点,可以执行:

$ systemd-analyze critical-chain

类似于 Bootchart,还可以生成 SVG 形式的启动流程图:

$ systemd-analyze plot > plot.svg

更多信息请参考 systemd-analyze(1)

使用 bootchart2

你还可以使用 Bootchart2 将启动流程可视化。

编译自定义内核

使用自定义内核可以减少启动时间和内存占用,但由于 Linux 内核的模块化特性以及 64 位架构的逐渐标准化,这些好处可能没有预期的那么大。具体信息请参考内核#编译

官方内核的模块默认压缩等级为 ZSTD_CLEVEL=19,但 SSD 可能更适合使用 ZSTD_CLEVEL=1

建议将会用到的存储和文件系统模块嵌入到内核中,以使用 Arch 的启动流程#Running_without_initramfs

Initramfs

最佳做法是 Arch 的启动流程#Running_without_initramfs

mkinitcpio 默认使用 baseudev 钩子,将它们替换为 systemd可以提升启动速度,具体细节请参考 Mkinitcpio#常用钩子。如果要替换 fsck 钩子,请参考 Fsck#启动时检查

#编译自定义内核类似,initramfs 也可以被精简。最简单的方法是包含 mkinitcpioautodetect 钩子。Booster 可以生成比 mkinitcpiodracut 更小的 initramfs,并使用更快的单二进制文件 init. 参阅 极简 initramfsBooster#Removing modules 以获得更多信息。

取决于你的硬件(处理器和存储速度)不同,由于启动时更快的解压速度通常可以抵消掉从硬盘读取稍大的 initramfs 的负面影响,使用 lz4 取代默认的 zstd 压缩算法有可能会更快,具体细节请参考 Mkinitcpio#压缩方式(COMPRESSION)

选择合适的服务启动方式

systemd 的一个核心功能是 D-Bus 和 socket 激活。多数情况下建议使用该功能,它会使服务只在初次访问时启动,通常来说这是件好事(例如 cups.service 在桌面环境通常没必要开机启动,而启用 cups.socket 会使只在打印时启动服务)。

但如果有个服务(以 upower 为例)始终会在开机时启动,那尽早将其启动有可能会减少启动耗时,该操作可通过启用 upower.service 达成(前提是已配置了启动文件,多数情况下都是如此)。

这样 systemd 就会尽早启动 UPower,而不会引起 socket 或 D-Bus 激活的竞争。

分批启动

有些硬件使用了分批启动(Staggered spin-up,SSP),会使系统按顺序探测 ATA 接口,从而使硬盘逐个轮流启动,以降低耗电峰值。这会降低启动速度,且由于多数消费级硬件在通电后就会立即启动,因此并没有提供什么优势。执行以下命令可以检查是否启用了分批启动:

# dmesg | grep SSS

无输出表示没有使用该功能。

可以将 libahci.ignore_sss=1 添加到内核参数以禁用该功能。

挂载文件系统

借助 mkinitcpiofsck 钩子,你可以通过在内核命令行中将 ro 改为 rw 来避免对 root 分区进行影响性能的重挂载:一个选择是使用 rootflags=rw,other_mount_options 来设置相关选项。必须从 /etc/fstab 中移除对应的条目,否则 systemd-remount-fs.service 仍会尝试应用这些设置。或者,也可以尝试屏蔽(mask)此服务单元。

如果根文件系统是 Btrfs,就不需要和其他文件系统一样每次启动都进行 fsck。在这种情况下,可以移除 mkinitcpio 的 fsck 钩子。你也可以选择屏蔽(Mask) systemd-fsck-root.service,或者使用内核命令行fsck.mode=skip来告诉根文件系统跳过 fsck。没有 mkinitcpio 的 fsck 钩子,systemd 仍会使用 systemd-fsck@.service 对任何相关的文件系统进行 fsck。

你也可以移除/etc/fstab中的 API 文件系统,因为 systemd 会自动挂载它们(列表见 pacman -Ql systemd | grep '\.mount$')。用户可能看到从 sysvinit 迁移过来的 /tmp 条目,但你可能已经注意到,从上面的命令可以看出,systemd 已经处理了这个问题。因此,/tmp 条目可以安全地移除。

其他文件系统,比如 /home 或者 EFI 系统分区,可以使用自定义的挂载单元进行挂载。向挂载参数中添加 noauto,x-systemd.automount 会延迟挂载分区,直到首次访问时才进行 fsck 和挂载,从而减少启动过程中需要 fsck 或挂载的文件系统数量,帮助加快启动速度。

注意:
  • 这将使你的 /home 文件系统类型变成 autofs,默认情况下,locate 会忽略它。自动挂载 /home 的加速效果可能不会超过一两秒,具体取决于你的系统,因此这个技巧可能并不值得尝试。
  • 如果系统安装在一个 btrfs 子卷中(具体来说:根目录 / 本身是一个子卷),并且 /home 是一个独立的文件系统,你可能还需要防止创建一个 /home 子卷。可以通过屏蔽 home.conf 临时文件来实现:ln -s /dev/null /etc/tmpfiles.d/home.conf

精简启动阶段输出信息

对于某些用户,特别是 SSD 用户,TTY 的龟速实际上成为了性能瓶颈,精简输出信息实际上有利于提高性能。具体建议请参考静默启动

替换启动引导器

替换引导加载程序(例如换成 systemd-boot 这种简单的引导器)可能会减少数秒的启动时间。

在可用的情况下,只使用一个 EFI boot stub 可以进一步降低启动耗时。

内核参数

有些内核参数可以提升启动性能。

如果不需要 systemd-gpt-auto-generator,使用 systemd.gpt_auto=no 可能会减少 0.2~3 秒的启动时长。如果根分区是 Btrfs 且没有使用 initramfs 进行启动,那 systemd-gpt-auto-generator 不会起效[1]

cryptomgr.notests 会禁用自测试,但效果可能不大。

挂起到内存

减少启动时长的最好方法是完全不用启动,可以考虑转而将系统挂起到内存