在我拥有或使用过的所有计算机中,启动最快的是 20 世纪 80 年代的计算机;当您的手从电源开关移到键盘时,BASIC 解释器已准备好接受您的命令。现代计算机启动时间从笔记本电脑的 15 秒到小型家用服务器的几分钟不等。为什么启动时间会有如此大的差异?
20 世纪 80 年代的微型计算机直接启动到 BASIC 提示符,它有一个非常简单的 CPU,一旦通电,就开始从内存地址获取和执行指令。由于这些系统在 ROM 中有 BASIC,因此没有加载时间——您可以非常快速地获得 BASIC 提示符。同一时代的更复杂的系统,例如 IBM PC 或 Macintosh,需要相当长的时间才能启动(约 30 秒),但这主要是由于必须从软盘读取操作系统 (OS)。在能够加载操作系统之前,只有几秒钟花在固件上。
现代服务器通常在固件中花费数分钟而不是数秒,然后才达到从磁盘启动操作系统的程度。这在很大程度上是由于现代系统复杂性的增加。CPU 不再能够启动并以全速开始执行指令;我们已经习惯了 CPU 频率缩放、节省大量功耗的空闲状态以及多个 CPU 内核。事实上,在现代 CPU 内部,有数量惊人的更简单的 CPU,它们有助于启动主 CPU 内核并提供运行时服务,例如在 CPU 过热时节流频率。在大多数 CPU 架构上,在 CPU 内部这些内核上运行的代码以不透明的二进制 blob 形式提供。
在 OpenPOWER 系统上,在 CPU 内部的每个内核上执行的每条指令都是开源软件。在使用 OpenBMC 的机器上(例如 IBM 的 AC922 系统和 Raptor 的 TALOS II 和 Blackbird 系统),这也扩展到在基板管理控制器上运行的代码。这意味着我们可以深入了解从您插入电源线到显示熟悉的登录提示符之间需要多长时间。
如果您是 Linux 内核团队的一员,您可能会启动很多内核。如果您是固件团队的一员,您可能会启动许多不同的固件映像,然后启动操作系统以确保您的固件仍然有效。如果我们能够缩短硬件的启动时间,这些团队可以变得更有效率,最终用户在设置系统或重启以安装固件或操作系统更新时可能会感激不尽。
多年来,Linux 发行版的启动时间已经进行了许多改进。现代 init 系统可以很好地处理并发和按需操作。在现代系统上,一旦内核开始执行,可能只需几秒钟即可到达登录提示符。这几秒钟不是优化启动时间的地方;我们必须更早地进行:在到达操作系统之前。
在 OpenPOWER 系统上,固件通过启动存储在固件闪存芯片中的 Linux 内核来加载操作系统,该内核运行一个名为 Petitboot 的用户空间程序,以查找保存用户想要启动的操作系统的磁盘,并使用 kexec() 跳转到它。这种代码重用利用了为加快 Linux 启动速度所做的努力。即便如此,我们还是在内核配置和用户空间中找到了可以改进的地方,并且可以轻松地缩短启动时间几秒钟。通过这些优化,启动 Petitboot 环境仅占启动时间的个位数百分比,因此我们必须在其他地方寻找更多改进。
在 Petitboot 环境启动之前,还有一个先前的固件称为 Skiboot,在此之前还有 Hostboot。在 Hostboot 之前是 Self-Boot Engine,它是芯片上的一个单独内核,它启动单个 CPU 内核并从三级缓存中执行指令。这些组件是我们可以在缩短启动时间方面取得最大进展的地方,因为它们占据了绝大部分时间。也许这些组件中的一些优化不够,或者没有尽可能多地并行执行?
另一种攻击途径是重启时间而不是启动时间。在重启时,我们真的需要重新初始化所有硬件吗?
与任何现代系统一样,改进启动(和重启)时间的解决方案是并行执行更多操作、处理遗留问题以及(可以说)作弊的混合。
Stewart Smith 将于 1 月 21 日至 25 日在新西兰基督城的 linux.conf.au 会议上展示 更快启动 的演讲。
9 条评论