提高性能/引导过程
提高系统的启动性能可以缩短启动等待时间,并作为一种了解特定系统文件和脚本如何相互交互的手段。本文尝试汇总提高 Arch Linux 系统启动性能的方法。
分析启动过程
使用 systemd-analyze
systemd 提供了一个名为 systemd-analyze 的工具,可用于显示启动过程的时间详情,包括一个显示单元等待其依赖项的 SVG 图表。你可以查看哪些单元文件导致启动过程变慢,进而相应地优化你的系统。
要查看启动时在内核空间 (kernelspace) 和用户空间 (userspace) 花费的时间,只需使用
$ systemd-analyze
要列出已启动的单元文件,并按每个单元启动所需的时间排序
$ systemd-analyze blame
在启动过程的某些时间点,某些事项必须在给定单元成功后才能继续。要查看哪些单元处于启动链中的这些关键点,请执行
$ systemd-analyze critical-chain
你还可以创建一个 SVG 文件,以图形方式描述你的启动过程,类似于 Bootchart
$ systemd-analyze plot > plot.svg
使用 bootchart2
你也可以使用 Bootchart2 来可视化启动序列。
编译自定义内核
编译自定义内核可以减少启动时间和内存占用。虽然随着 64 位架构的标准化和 Linux 内核的模块化特性,这些收益可能不如预期那样显著。更多信息请参阅 Kernel#Compilation。
官方内核模块的压缩级别是在 ZSTD_CLEVEL=19 下构建的。但对于 SSD,ZSTD_CLEVEL=1 可能会更好。
建议将根卷的存储和文件系统模块构建为内置 (built-in),以便实现 在没有 initramfs 的情况下运行。
Initramfs
如果在你的配置中可行,在没有 initramfs 的情况下运行 应该是最快的方式。
mkinitcpio 默认使用 base 和 udev 钩子 (hooks)。可以通过将它们替换为 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 最小化 微代码镜像 (Microcode image) [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)在启动过程中总是会被启动,那么通过尽可能早地启动它可能会缩短整体启动时间。如果服务文件已为此进行了配置(大多数情况如此),可以通过 启用 (enabling) upower.service 来实现。
这将导致 systemd 尽可能快地启动 UPower,而不会与套接字或 D-Bus 激活产生竞态。
交错启动 (Staggered spin-up)
某些硬件实现了 交错启动 (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 将继续尝试应用这些设置。或者,可以尝试屏蔽 (mask) 该单元。
如果根文件系统使用的是 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,而autofs默认被 locate 忽略。自动挂载/home的提速可能不超过一两秒,具体取决于你的系统,因此这个技巧可能不值得尝试。 - 如果系统安装在 btrfs 子卷中(具体来说:根目录
/本身是一个子卷)且/home是一个独立的文件系统,你可能还想防止创建/home子卷。屏蔽home.conf临时文件:ln -s /dev/null /etc/tmpfiles.d/home.conf。
减少启动时的输出
对于某些系统,特别是那些配备 SSD 的系统,TTY 的缓慢性能实际上是一个瓶颈,因此更少的输出意味着更快的启动。有关建议,请参阅 静默启动 (Silent boot) 文章。
更换启动加载程序
更换你的 启动加载程序(例如,使用更简单的启动加载程序,如 systemd-boot)可能会缩短几秒钟的启动时间。
如果你的配置允许,请尝试仅使用 EFI boot stub 以获得更短的启动时间。
挂起到内存
减少启动时间最好的方法就是根本不启动。考虑改为将 系统挂起到 RAM。