SDB:Boot performance

跳转至: 导航, 搜索

Template:Working

本文主要研究怎样让 openSUSE 在不影响桌面用户功能的情况下,尽可能启动的更快。因此:
  • 本文和噱头般的几秒启动不同,不但要启得来,还要动得了,不是为了片面追求启动速度,而影响功能。当然一些养眼的功能本文会告诉您怎么去掉,但本文并不会去掉它们。毕竟养眼也是一个卖点。所以本文不会夸海口说能保证几秒启动,但肯定会比没优化启动的快。一般都在一分钟以内,如果您遇到了特殊的问题,请在 talk 页面留言。
  • 本文是尽可能启动的快,因此也就存在瓶颈(多数暂时的)。
  • 本文主要面向桌面用户,同时兼顾服务器用户的参考价值。
  • 本文主要以我的个人电脑(Thinkpad T61)为例,因此就可能出现我开启的服务你没开启(因此也不需要优化),或者我优化的东西你优化了却没有效果的尴尬情况。
注意 风险提示:本文是一篇 SDB 文章,openSUSE 对此间内容不负责任,因此其中内容搞死了你的系统只能说抱歉,可以帮你修,但搞的可能性还是有的。这是真的风险提示,不是敷衍了事。因此非高级用户请谨慎尝试。

启动过程:Linux 下的启动过程是指从按下电源键到出现登录管理器的过程。因此 KDM/GDM 的速度并不在本文讨论之列(你可能 20 秒就完成了启动过程,但登录过程却进行了 40 秒,然后到论坛上说我的电脑启动速度是 1 分钟,这是常见的错误)。

启动过程主要涉及以下几部分:

initramfs => 挂载 root => 加载内核 => sysvinit/systemd

initramfs

initramfs 就是 /boot 目录的 initrd-3.6.3-1-desktop,是一个最小 Linux 环境的 cpio 压缩包。里面有一些 Linux 的基本命令,如 cp, grep, mkdir, ls, kill,以及一些用于加载 Linux 内核的 shell 脚本(bash 脚本)。主要通过 mkinitrd 命令自动生成。在按下电源键后会被 grub/grub2 载入内存。

可以省略 initramfs 直接加载内核,以避免不必要的检测(主要是关于文件系统的,它需要探测磁盘类型和文件系统格式以正确找到内核位置,如 RAID 磁盘阵列检测,这东西普通桌面用户都没有),因为内核后来还要把大部分检测再做一遍。但是一些文件系统并不支持直接从中载入内核(如 btrfs)。

完全禁用 initramfs(ext4)

所以针对 ext4 这样的主流文件系统,你可以做出调整,让它直接启动内核,以提高速度(默认约 10 秒):

  • 编辑 /etc/grub2/grub.cfg
sudo vi /boot/grub2/grub.cfg(或者使用 YaST 的引导加载器来编辑,推荐后者)
               echo    'Loading Linux 3.6.3-1-desktop ...'
               linux   /vmlinuz-3.6.3-1-desktop root=UUID=9b9aa9d9-760e-445c-a0ab-68e102d9f02e 
               resume=/dev/disk/by-id/ata-SAMSUNG_HN-M101MBB_S2R8J9BB808817-part1 
               splash=silent quiet showopts  vga=0x317

改成

               echo    'Loading Linux 3.6.3-1-desktop ...'
               linux   /vmlinuz-3.6.3-1-desktop root=/dev/sda6 rootfstype=ext4
               resume=/dev/disk/by-id/ata-SAMSUNG_HN-M101MBB_S2R8J9BB808817-part1 
               splash=silent quiet showopts  vga=0x317

其中红色部分可以通过“df -T”命令来看到。如:

df -T
文件系统       类型         1K-块      已用     可用 已用% 挂载点
rootfs         rootfs    51922016  44278012  1861388   96% /
devtmpfs       devtmpfs   1525444         8  1525436    1% /dev
tmpfs          tmpfs      1535564      2252  1533312    1% /dev/shm
tmpfs          tmpfs      1535564       656  1534908    1% /run
/dev/sda6     ext4     51922016  44278012  1861388   96% /

大家可以看到 rootfs 的挂载点是 /,而 / 对应的分区编号是 /dev/sda6,分区格式是 ext4。

使用 dracut(btrfs)

针对 btrfs,可以尝试使用最新的 dracut 程序。它和 initramfs 同为制作初始化内存文件系统(init+ram+fs)的工具,但不同点在于它设计的目标是尽力减少不必要的硬编码,因此它做出的压缩包很小,所以载入很快。

裁剪 initramfs

使用如下命令比较一下:

17:36:47 marguerite at ~ say:
卐 ls -lh /boot/vmlinuz-* /boot/initrd-*
-rw-r--r-- 1 root root  17M 10月 23 02:09 /boot/initrd-3.6.3-1-desktop
-rw-r--r-- 1 root root 5.0M 10月 22 16:12 /boot/vmlinuz-3.6.3-1-desktop

离谱吧,你的 initrd 比你的内核大 3 倍多。那先载入它还不如直接载入内核呢。

对于 btrfs 这种直接载不了内核的文件系统,可以采用这种方法来裁剪它:

17:39:13 marguerite at ~ say:
卐 rpm -qf /lib/mkinitrd/scripts/setup-* | sort -u
cifs-utils-5.5-2.2.2.x86_64 // 用于挂载 Windows 的 ntfs 磁盘
cryptsetup-1.4.2-3.2.1.x86_64 // 用于挂载加密磁盘
device-mapper-1.02.63-26.1.1.x86_64 // 跟 RAID 有关,什么关系说不好
dmraid-1.0.0.rc16-18.2.1.x86_64 // RAID 阵列
kpartx-0.4.9-3.1.1.x86_64 // 同上
lvm2-2.02.84-26.1.1.x86_64 // 虚拟块设备
mdadm-3.2.5-3.3.2.x86_64 // 用于挂载多路径设备
mkinitrd-2.7.0-62.2.1.x86_64
multipath-tools-0.4.9-3.1.1.x86_64 // 用于挂载多路径设备
plymouth-scripts-0.8.5.1-1.3.1.noarch
splashy-0.3.13-35.1.1.x86_64

这就是除了那些 Linux 基本命令和用于加载内核的脚本之外的,会往 initrd 里写东西的 RPM。有注释的都是对桌面用户没什么实际作用的,因为它的功能你没有。

直接删除这些 RPM,可以,但不推荐,因为它能把你的 YaST 卸载一半,里面还不乏常用的如 yast-network。

另一个方法是屏蔽掉将这些 RPM 中的内容写入到 initrd 的脚本,这样重新生成 initrd 的时候就不会写入这些东西了。

cd /lib/mkinitrd/scripts/
sudo mv setup-dmraid.sh setup-dmraid.sh.bak
sudo ln -s /bin/true setup-dmraid.sh // 这种方法很常见,又叫 mask。

接着把 boot 开头的也这么干掉,然后运行 sudo mkinitrd 重新生成 initrd。但这种方法在相关软件包升级后会被覆盖掉,要重新做。

但实际上我们屏蔽掉这些包几乎是洁癖在作怪,因为 initrd 只能减少 1MB 的份量。最大的份量在于 plymouth-scripts 和 splashy,两者都是图片,屏蔽掉能减少 10 MB 的份量,但你就没有漂亮的 grub2 和启动动画了。因此除非你能把启动过程优化得一闪即逝(如 ext4),否则最好不要屏蔽这些包。

挂载 root

这主要涉及文件系统的问题。ext4 一般不需要看这里。

对于 btrfs,如果你没有开启一些优化选项,或者你的 btrfs 分区创建的太早(比如在 12.1 你就上了 btrfs)以至于那时候并没有优化选项可以开启,那么它开机会进行预热,导致挂载的时间相当长,以至于下一步,加载内核,变得很慢,50 GB btrfs root 分区就能达到 135s 才能挂载好分区的情况(可以想象 OBS 那种阵列服务器会是什么样的壮观景象)。因为加载内核不只是载入 /boot(一般是 ext4)中的 vmlinux 主内核,还有 /lib/modules 中的内核模块,而很不幸这些模块在 btrfs 分区,没预热好不能挂载也就不能访问,于是就卡住了。

btrfs 的优化请见 openSUSE:Btrfs

加载内核

不要使用 debug 内核。那个内核设计的就是运行很慢。

可以添加 libachi.ignore_sss=1 和 raid=noautodetect 到 /etc/grub2/grub.cfg 以让内核不检查文件系统是否为 RAID。

另外,作为桌面用户,不要使用 LVM 这样的虚拟块设备存储技术。它会让下面的 systemd 引入一个超慢的服务来设置它。

最后,在有条件的情况下(意思是你会编译内核也能编译内核),可以把你常用的内核模块编译到内核里。理论上越多的磁盘 IO 会越慢,但实际效果微乎其微,除非你的文件系统有 bug(比如 3.2 内核之前的 btrfs 的 IO 不但很慢还很吃 CPU)。

sysvinit

systemd