性能优化/启动过程 - Arch Linux 中文维基

跳转到内容

# 性能优化/启动过程

来自 Arch Linux 中文维基
< 性能优化

相关文章

- 性能优化
- 静默启动
- Daemon
- Kexec

翻译状态：

- 本文（或部分内容）译自 Improving performance/Boot process，最近一次同步于 2025-04-03，若英文版本有所更改，则您可以帮助同步与翻译更改的内容。
- 您可以在 ArchWiki 的对应页面找到本文翻译的原始修订历史。
- 本文可能与英文原文存在出入。

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

## 启动过程分析

### 使用 systemd-analyze

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

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

    $ systemd-analyze

提示：如果系统使用 UEFI 引导，且启动引导器实现了 systemd 的启动引导器接口（目前只有 GRUB 和 systemd-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 默认使用 `base` 和 `udev` 钩子，将它们替换为 `systemd`可以提升启动速度，具体细节请参考 Mkinitcpio#常用钩子。如果要替换 `fsck` 钩子，请参考 Fsck#启动时检查。

与#编译自定义内核类似，initramfs 也可以被精简。最简单的方法是包含 mkinitcpio 的 `autodetect` 钩子。Booster 可以生成比 mkinitcpio 和 dracut 更小的 initramfs，并使用更快的单二进制文件 init. 参阅极简 initramfs 或 Booster#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` 添加到内核参数以禁用该功能。

## 挂载文件系统

借助 mkinitcpio 的 `fsck` 钩子，你可以通过在内核命令行中将 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` 会禁用自测试，但效果可能不大。

## 挂起到内存

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

分类：​

- 启动过程

性能优化/启动过程
添加话题