systemd优化

原文:https://www.freedesktop.org/wiki/Software/systemd/Optimizations/

那么你正在开发Linux发行版或设备,需要非常快速的启动?

systemd已经可以为Core OS提供<1s的启动时间(仅限用户空间,即仅由systemd控制的位),对于更简单(但是现代的,即SSD)笔记本电脑上的完整最新桌面环境,如果配置了<2s正确(例如:http//git.fenrus.org/tmp/bootchart-20120512-1036.svg)。在这个页面中,我们想提出一些如何实现这一点的想法,如果最终的启动时间不足以让我们认为改进的空间是我们希望迟早实现的。如果您有兴趣在systemd中投入工程人力以缩短启动时间,那么这个列表可能包含一些好的建议。

当然,在优化之前,您应该检测启动以生成分析数据,因此请确保您了解systemd-bootchart,systemd-analyze和pytimechart的方法!没有分析的优化是过早的优化!

请注意,systemd的快速性能是其设计的副作用,但不是主要的设计目标。现在系统(和Fedora使用它)已经优化很少,仍然有很大的改进空间。仍有许多低悬的水果可供挑选!

我们非常有兴趣将优化工作合并到systemd upstream。但请注意,我们注意不要合并会严重限制代码的通用实用性或可靠性的工作,或者使systemd更难维护的工作。因此,如果您正在为systemd进行优化,请尝试将您的东西保持为主线。如有疑问,请问我们。

这些分布采用了不同级别的系统。虽然在Debian的启动过程中有许多兼容性脚本,但Fedora的功能要少得多(但仍然太多)。为了获得更好的性能,请考虑禁用这些脚本或使用其他分发。

我们打算默认优化上游分发(特别是Fedora),这样就不需要进行这些优化。然而,这将花费一些时间,特别是因为当不能破坏通用有用性时,进行这些改变通常不是微不足道的。

您可以在不编写任何代码的情况下优化(本地):

  1. 确保不使用任何伪块设备存储技术(如LVM(默认情况下由各种发行版安装,包括Fedora)),这会导致systemd-udev-settle.service单元被拉入。安装设备枚举很慢,很有趣而且大多已经过时了。由于LVM(仍然)尚未更新以正确处理Linux基于事件的设计,因此仍然需要设置枚举设备枚举,但它会大大降低启动速度。在Fedora上,使用“systemctl mask fedora-wait-storage.service fedora-storage-init-late.service fedora-storage-init.service”来摆脱所有这些存储技术。当然,如果您实际使用LVM安装了系统,请不要尝试这样做。(目前唯一正确处理此问题的假块设备存储技术并没有'
  2. 如果使用initrd,请考虑绕过initrd。在Fedora上,确保在没有加密的普通磁盘上安装操作系统,并且在执行此操作时没有LVM / RAID / ...(加密/家庭很好)。然后,只需编辑grub.conf并从配置中删除initrd,并更改root = kernel命令行参数,使其使用内核设备名称而不是UUID,即“root = sda5”或适合您系统的名称。同时使用“rootfstype = ext4”(或根据需要)指定根FS类型。请注意,如果您有多个硬盘,使用内核设备名称并不是那么好,但是如果您正在为笔记本电脑执行此操作(即使用单个硬盘驱动器),这应该没问题。请注意,您不需要重建内核以绕过initrd。分发内核(至少Fedora'
  3. 考虑禁用SELinux和审核。出于安全原因,我们建议保留SELinux,但事实是,如果禁用它,可以保存100毫秒的启动。在内核cmdline上使用selinux = 0。
  4. 考虑禁用普利茅斯。如果用户空间在少于1秒内启动,则启动启动几乎没用,因此请考虑在内核命令行上传递plymouth.enable = 0。普利茅斯通常很快,但目前仍然迫使显卡设备枚举,这是很慢的。禁用普利茅斯删除了这一点的启动。
  5. 考虑卸载syslog。该期刊无论如何都用在较新的系统系统上,对于台式机,嵌入式甚至许多服务器来说,通常都足够了。只需卸载所有syslog实现,并记住“journalctl”将为您提供经典/ var / log / messages消息日志的像素完美副本。要使日志日志持久(即,以便它们在引导时不会丢失),请确保运行“mkdir -p / var / log / journal”。
  6. 考虑屏蔽一些冗余的分发启动脚本,这会人为地减慢启动速度。例如,在Fedora上,屏蔽fedora-autoswap.service fedora-configure.service fedora-loadmodules.service fedora-readonly.service是个好主意。同时删除所有与LVM / RAID / FCOE / iSCSI相关的软件包,即使没有使用特定类型的存储,也会大大减慢启动速度(如果因为某些重要的软件包需要它们而无法删除这些RPM,至少要屏蔽相应的软件包服务)。
  7. 控制台输出很慢。因此,如果您测量启动时间并运送系统,请确保在命令行上使用“quiet”并禁用systemd调试日志记录(如果您之前已启用它)。
  8. 考虑从系统中删除cron并改为使用systemd计时器单元。计时器单元目前不支持日历时间(即不能用于在每个星期一早上6点生成东西),但可以“每隔7天运行一次”),但对于通常的/etc/cron.daily/,/ etc / cron.weekly /,...应该足够好,如果执行的时间无关紧要(只需添加四个小服务和计时器单元来支持这些目录。最终我们可以支持这些开箱即用,但在那之前,只需为此编写自己的文章。
  9. 如果您使用的是设备,请考虑在已发布的设备中禁用预读集合,但请启用预读重播。
  10. 如果您使用的是设备,请确保在内核中构建所需的所有驱动程序,因为模块加载速度很慢。如果你构建一个发行版至少构建了90%所有人需要进入内核的东西,即至少USB,AHCI和HDA!
  11. 如果可行,请在启动时使用libahci.ignore_sss = 1。
  12. 使用不再引入ConsoleKit的现代桌面。例如GNOME 3.4。
  13. 如果您正在构建桌面或设备,请摆脱本地MTA。即在Fedora上删除默认安装的sendmail RPMs(仍然!)。
  14. 如果您构建设备,请不要忘记systemd的各种组件是可选的,并且可能在构建期间被禁用,有关详细信息,请参阅“./configure --help”。例如,如果您从未拥有本地控制台用户,则摆脱虚拟控制台设置(实际上这是缓慢的主要原因)。此外,如果您根本没有本地用户,请考虑禁用logind。并且在设备上经常不需要更多组件。
  15. 不言而喻:如果在启动时启动的内容较少,启动速度会更快。所以运行“systemctl”并检查是否有你不需要的东西并禁用它,甚至删除它的包。
  16. 不要使用调试内核。调试内核很慢。Fedora在每个版本的开发阶段专门使用调试内核。如果您关心启动性能,请在关闭调试的情况下重新编译这些内核,或者等待最终的分发版本。这是一个巨大的差异。这也意味着,如果您发布Fedora预发布版本的启动性能数据,那么您做错了。;-)关于如何快速启动的基础知识。现在,这里有一个不完整的事情列表,我们希望看到在systemd(和其他地方)短期或长期内有所改进,需要一些黑客攻击(有时更多,有时甚至更少):

  17. 摆脱systemd-cgroups-agent。目前,只要systemd cgroup运行为空,内核就会调用“systemd-cgroups-agent”工具,然后系统会通知systemd。对这个工具的需求应该真的消失,这将在启动时节省许多分叉进程,并且应该使事情更快(特别是关闭)。这需要引入新的内核接口来获取运行为空的cgroup的通知,例如通过cgroupfs上的fanotify()。

  18. 在systemd的readahead实现中使用EXT4_IOC_MOVE_EXT。这允许重新排序/碎片整理引导所需的文件。根据http://e4rat.sourceforge.net/的数据,这可能会将启动时间缩短到40%。实现并不简单,但鉴于我们已经支持btrfs碎片整理,并且存在的示例代码(e4rat as linked)应该相当简单。
  19. 使用XZ左右压缩预读包文件。由于这些天的启动往往明显受IO限制(而不受CPU限制),因此通过压缩来减少包文件的IO负载可能是有意义的。由于我们已经依赖XZ,我们建议使用XZ。
  20. 更新readahead逻辑以预先缓存目录(除文件外)。
  21. 改进单元依赖图计算逻辑中的几个算法,以及单元文件加载。例如,现在当加载单元时,我们将它们与其他加载单元的子集匹配,以便在适当的位置添加它们之间的自动依赖关系。通常匹配的单元组很小,但复杂度目前为O(n ^ 2),这可以进行优化。由于依赖图中的单元文件加载和计算是PID 1的唯一主要的,同步的,计算密集的位,并且在任何服务启动之前执行,这应该带来相关的改进,尤其是在具有大依赖图的系统上。
  22. 向X添加套接字激活。由于X的特殊套接字分配语义,这仅对display:0有用。这应该允许X启动与其客户端的并行化。
  23. 通常的内务处理:摆脱基于shell的服务(即SysV init脚本),用单元文件替换它们。如果可能,不要使用Type = forking和排序依赖项,而是使用Type = simple的套接字激活。这样可以为您的服务提供更好的并行启动。此外,如果您不能使用套接字激活,至少考虑修补您的服务以支持Type = notify代替Type = forking。考虑按需激活很少使用的服务(例如,打印机服务),并在启动时启动经常使用的服务,而不是在使用它们之前将其延迟。
  24. 考虑使用systemd进行会话,就像Tizen这样做的方式。这仍然需要在systemd上游的一些爱情顺利骑行,但我们肯定希望迟早这样,即使对于普通的桌面。
  25. 为服务单元添加一个选项,以暂时提高重要服务的启动代码的CPU和IO优先级。但是请注意,我们假设这不会带来太多,因此建议仅在很晚才研究这个问题。由于启动往往是IO绑定,因此诸如readahead之类的解决方案可能比优先考虑服务启动IO更有趣。此外,这可能总是需要一定量的手动配置,因为自动确定哪些服务很重要(如果不是不可能),因为我们无法正确跟踪其他服务等待的服务。
  26. 与上一项相同,但暂时降低了不重要叶服务的启动部分的CPU / IO优先级。这可能比11更有用,因为更容易确定哪些过程无关紧要。
  27. 为AF_UNIX添加内核sockopt以增加SOCK_DGRAM套接字的最大数据报队列长度。这将允许我们在syslog和日志套接字中排队更多的日志记录数据报,从而移动syslog / journal客户端必须阻止的点,然后它们的消息写入在引导过程中稍后完成。当前的内核默认值相当低,为10.(作为临时hack,可以在全局范围内增加/ proc / sys / net / unix / max_dgram_qlen,但这有意义超出systemd,应该可以避免。)内核补丁到使这项工作最有可能是微不足道的。通常,这应该允许我们提高SOCK_DGRAM或SOCK_SEQPACKET类型的AF_UNIX套接字的客户端和服务器之间的并行化级别。再说一遍:上面的列表包含了我们希望在systemd中看到的内容。我们没有对这些功能进行太多的分析,但是我们有足够的指示假设这些位会带来一些改进。但是,如果您正在努力,请始终准备好您的分析工具。