提升系統的啟動性能可以縮短啟動等待時長,還能學習系統文件和腳本見交互的方式。本文整合了數種提升 Arch Linux 啟動性能的方式。
啟動過程分析
使用 systemd-analyze
systemd 提供了一個名為 systemd-analyze
的工具,可用於顯示有關啟動過程的計時細節, 包括一個顯示各單元等待其依賴項的 svg 圖。您可以看到哪些單元文件導致啟動過程減慢, 然後可以相應地優化系統.
要查看啟動時在內核/用戶空間中消耗的時間, 只需使用:
$ systemd-analyze
按照耗費時間順序,列出啟動各個單元耗費的時間:
$ 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
會禁用自測試,但效果可能不大。
掛起到內存
減少啟動時長的最好方法是完全不用啟動,可以考慮轉而將系統掛起到內存。