提高性能/引导过程
提高系统的启动性能可以减少启动等待时间,并有助于更深入地了解某些系统文件和脚本如何相互作用。本文旨在汇总提高 Arch Linux 系统启动性能的方法。
分析启动过程
使用 systemd-analyze
systemd 提供了一个名为 systemd-analyze 的工具,可用于显示启动过程的详细时间信息,包括一个 SVG 图,展示了单元(unit)在等待其依赖项。您可以找出哪些单元文件导致您的启动过程变慢,然后相应地优化您的系统。
要查看启动时花费在内核空间和用户空间的时间,只需使用
$ systemd-analyze
要列出启动单元文件,按它们各自启动所花费的时间排序
$ systemd-analyze blame
在启动过程的某些阶段,事情无法继续,直到给定的单元成功。要查看哪些单元处于这些关键的启动链环节,请执行
$ systemd-analyze critical-chain
您还可以创建一个 SVG 文件,以图形方式描述您的启动过程,类似于 Bootchart。
$ systemd-analyze plot > plot.svg
有关详细信息,请参阅 systemd-analyze(1)。
使用 bootchart2
您也可以使用 Bootchart2 来可视化启动序列。
编译自定义内核
编译自定义内核可以减少启动时间和内存使用。尽管 64 位架构已标准化,且 Linux 内核具有模块化特性,但这些优势可能不如预期那么大。有关更多信息,请参阅 Kernel#Compilation。
官方内核模块的压缩级别使用 ZSTD_CLEVEL=19 构建。但对于 SSD,ZSTD_CLEVEL=1 可能更好。
建议将用于存储和文件系统的模块内置到根卷中,以便 无需 initramfs 即可运行。
Initramfs
如果您的设置允许,无需 initramfs 即可运行应能提供最快的速度。
mkinitcpio 默认使用 base 和 udev 钩子。通过将它们替换为 systemd 可以实现更快的启动时间。有关更多详细信息,请参阅 Mkinitcpio#Common hooks。如果替换 fsck 钩子,请参阅 Fsck#Boot time checking。
与#编译自定义内核类似,initramfs 也可以进行瘦身。一种简单的方法是包含 mkinitcpio 的 autodetect 钩子。Booster 生成的 initramfs 比 mkinitcpio 或 dracut 生成的更小,并具有快速的单二进制 init。请参阅 Minimal initramfs 或 Booster#Removing modules。
根据您的硬件(处理器和存储速度),使用 lz4 而不是默认的 zstd 压缩选项可能会更快,因为启动时更快的解压缩速度通常会抵消 initramfs 从磁盘读取时稍大的尺寸。请参阅 Mkinitcpio#COMPRESSION。
如果您使用 无需 initramfs 即可运行或 Booster,您还可以最小化 intel-ucode 的 微码映像 [1]。
/etc/pacman.d/hooks/shrink-intel-ucode
[Trigger] Type = Package Operation = Install Operation = Upgrade Target = intel-ucode [Action] Description = Minimizing intel-ucode.img ... When = PostTransaction Depends = iucode-tool Exec = /usr/bin/iucode_tool -S /usr/lib/firmware/intel-ucode --overwrite --write-earlyfw=/boot/intel-ucode.img
选择合适的启动服务方式
systemd 的一个核心特性是 D-Bus 和套接字激活(socket activation)。在大多数情况下应优先使用此特性,因为它仅在服务首次被访问时启动,这通常是件好事(例如,在启动时启用 cups.service 对桌面用户通常没有用,不如启用 cups.socket,它只在实际打印时才启动服务)。
然而,如果您知道某个服务(如 upower)将在启动时始终被启动,那么尽早启动它可能会减少总体启动时间。这可以通过 启用 upower.service 来实现(如果服务文件已为此配置,大多数情况下都是如此)。
这将导致 systemd 尽快启动 UPower,而不会与套接字或 D-Bus 激活产生冲突。
交错启动
某些硬件实现了 交错启动(staggered spin-up),它会导致操作系统串行探测 ATA 接口,从而逐个启动驱动器并降低峰值功耗。这会减慢启动速度,并且在大多数消费级硬件上根本没有好处,因为驱动器在接通电源时会立即启动。要检查 SSS 是否正在使用
# dmesg | grep SSS
如果在启动过程中未使用,则不会有输出。
要禁用它,请在 内核参数中添加 libahci.ignore_sss=1。
文件系统挂载
得益于 mkinitcpio 的 fsck 钩子,您可以通过在内核行将 ro 更改为 rw 来避免可能耗时的根分区重新挂载:选项可以使用 rootflags=rw,other_mount_options 设置。该条目必须从 /etc/fstab 文件中删除,否则 systemd-remount-fs.service 将继续尝试应用这些设置。或者,可以尝试屏蔽该单元。
如果根文件系统使用 Btrfs,则不像其他文件系统那样需要在每次启动时进行 fsck。如果是这种情况,可以删除 mkinitcpio 的 fsck 钩子。您还可以屏蔽 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 已经处理了它。因此,可以安全地删除它。
其他文件系统,例如 /home 或 EFI 系统分区,可以使用自定义挂载单元进行挂载。在挂载选项中添加 noauto,x-systemd.automount 将缓冲对该分区的全部访问,并在首次访问时进行 fsck 和挂载,从而减少必须在启动过程中 fsck/挂载的文件系统数量。
- 这将使您的
/home文件系统类型为autofs,该类型默认被 locate 忽略。根据您的系统,自动挂载/home的速度提升可能不会超过一两秒,因此这个技巧可能不值得。 - 如果系统安装在 btrfs 子卷中(特别是:根目录
/本身就是一个子卷)并且/home是一个单独的文件系统,您也可能想防止创建/home子卷。屏蔽home.conftmpfile:ln -s /dev/null /etc/tmpfiles.d/home.conf。
减少启动时的输出
对于某些系统,特别是那些使用 SSD 的系统,TTY 的缓慢性能实际上是一个瓶颈,因此输出越少意味着启动越快。有关建议,请参阅 静默启动 文章。
更改引导加载程序
更改您的 引导加载程序(例如,使用更简单的引导加载程序,如 systemd-boot)可以减少几秒的启动时间。
如果您的设置允许,请尝试仅使用 EFI 引导存根以获得更短的启动时间。
挂起到内存
减少启动时间最好的方法是不启动。考虑将系统挂起到内存。