关于云计算:深入浅出-Ext4-块和-Inode-分配器的优化下

42次阅读

共计 6515 个字符,预计需要花费 17 分钟才能阅读完成。

作者 | Aneesh Kumar K.V、Mingming Cao、Jose R Santos、Andreas Dilger

翻译 | 焱融技术团队

在上一篇《深入浅出 Ext4 块和 Inode 分配器的优化(上)》中,咱们简略地回顾了 Ext3 块分配器的原理和以后的限度,以及介绍了 Ext4 多块分配器和它是如何解决 Ext3 文件系统面对的限度。本文,咱们将持续探讨对于 Ext4 和 Inode 分配器的相干内容。先从 Ext4 多块分配器的性能和劣势开始,逐渐介绍 Ext3 Inode 调配策略、Inode 调配对整体文件系统性能的影响、扭转块组的概念如何使性能晋升等内容。

Ext4 多块分配器的性能劣势在哪里?

与小文件相干的多块分配器性能劣势如图七所示,块更靠近了,因为它们是在雷同的本地(部分)组预调配空间被满足的。

与大文件相干的多块分配器的性能劣势如图八所示,块更靠近了,因为它们是在特定于 Inode 的预调配空间中被满足的。

图七:多块分配器的小文件性能

图八:多块分配器的大文件性能

下方表一显示了应用 data=orderedmount 选项比拟 Ext4 和 Ext3 分配器的 compilebench[5] 数量。Compilebench 尝试模仿一些在创立、编译、Patching、Stating 和读取内核树时常见的磁盘 IO 老化文件系统的场景,间接测量文件系统在磁盘填满和目录老化时,保护目录局部性的能力。

表一:Ext4 和 Ext3 分配器的 Compilebench 数量

分配器演化史

Ext4 中的 mballoc 分配器其实是 Alex Tomas(Zhuravlev)写的第三代分配器引擎。该分配器的前两个版本次要集中在大块调配(一次 1MB),而第三代致力于改良小文件调配。

即便在低速率 I/O 下,Ext3 应用的单块调配也不肯定是块间调配的好决策。Linux VFS 层将提交给内核的任何大的 I/O 宰割成页面大小的块,并强制文件系统调配单个块,而不提供对于该文件上其余未实现的 I/O 的任何信息。第一次调配的块通常是块组中的第一个闲暇块,并且不会致力去寻找适宜写入文件的数据量的闲暇块范畴。这会导致呈现蹩脚的调配决策,比方抉择的闲暇块范畴对于单个 write() 调用来说不够大。

在十分高的 I/O 速率(超过 1GB/s)下,单块调配引擎也会成为 CPU 瓶颈,因为每个块调配都会遍历文件系统分配器,扫描闲暇块并锁定,以更新数据结构。应用 mballoc,一项测试表明,通过升高每个调配块的 CPU 老本,能够在同一零碎上从 800 MB/s 进步到 1500 MB/s。

mballoc 的胜利要害是,基于尽可能多的文件数据块,作出智能调配判断的能力,这就须要为失常 I/O 开发提早调配。当 mballoc 对文件的大小,以及要调配多少数据块有很好的理解时,就能够作出良好的决策。

第一个版本的 mballoc 只应用了搭档分配器来调配间断的块,并将调配与闲暇 extent 的结尾对齐。尽管防止了屡次调配的寻道和聚合,带来了肯定水平上的性能晋升,但当 I/O 在 RAID 磁盘和条带范畴边界上正确对齐时,它在具备较低开销的 RAID 设施背后,并不是最优的抉择。

第二个版本的 mballoc 改良了搭档分配器以将大量调配与 RAID 设施边界对齐。这很容易间接从 RAID 几何构造的搭档位图中实现,该几何构造在每个条带中应用数据磁盘的二次方数字,只需在 RAID 边界大小进行搜寻搭档位图中的闲暇位即可。

防止 RAID 零碎的“读取 - 批改 - 写入”周期,能够使性能进步一倍以上,故而也防止了低廉的同步读取。在具备与条带边界对齐的读取缓存的 RAID 设施中,执行未对齐读取,将使从磁盘读取的数据量加倍并填充两个缓存行。

Ext4 超级块在 mke2fs 时间段内或应用 tune2fs 存储 RAIDgeometry 的字段时,mke2fs 为了主动填充这些字段,很可能在 mkfstime 为 XFS 实现的简单 RAID 几何探测也将被采纳。

在测试以后第三版 mballoc 的过程中,钻研了小文件 I/O 的性能,发现只有在调配给不同文件的块之间没有寻道时,能力显著进步总体性能。因而,组分配机制用于将小调配打包在一起,它们两头没有任何闲暇空间。过来,每个文件的开端总是保留或留下空间,“以防万一”有更多的块要调配。对于小文件,会强制在每次读取或写入后进行查找。应用提早调配,小文件的大小在调配时是已知的,不再须要每个文件之后的间隙。

以后的 mballoc 分配器能够将调配对齐到非二次方对齐的 RAID 几何构造,只管它的开销略微低廉一些。

在优化定位器方面,仍有许多工作要做。尤其是,mballoc 保留了 Ext2/3 块分配器的“扫描组以取得良好调配”行为。像 XFS 一样,实现一个更优化的内存中的 free-extent 搜寻,会进一步升高搜寻闲暇区的老本。

此外,初始化搭档位图也有一些老本。在挂载时执行此操作,就像第一版本的 mballoc 所做的那样,对于十分大的文件系统会带来不可承受的挂载提早。在首次拜访时,执行此操作会减少提早并侵害文件系统首次应用的性能。在挂载时,启动一个线程来扫描组并异步执行搭档初始化,将有助于防止这两个问题。

提早调配概述和实现原理

因为 Ext4 会应用 extent 映射来无效地示意大文件,所以能够很天然地一起解决多个块调配,而不是像 Ext3 那样每次只调配一个块。因为 buffer I/O 的块调配申请在 write_begin 工夫内一次通过 VFS 层传递,所以底层 Ext3 文件系统无奈预感并合并将来的申请。因而,提早调配被屡次提出,以反对缓冲 buffer I/O 的多个块调配。

简而言之,提早调配从 write() 操作时的块调配推延到了刷新页的工夫。这个办法有很多益处:它减少了将许多块调配申请组合成一个申请的可能性,缩小了碎片并节俭了 CPU 周期。同时,防止了对短期文件进行不必要的块调配。

通常,应用提早调配,VFS 不会在 write_begin() 中调配磁盘块,而是进行一般块查找。对于那些未映射的 buffer-heads,它会计算须要保留的块数(包含数据块和元数据块),Ext4 块和 Inode 分配器的改良保留了它们,以确保文件系统中有足够的闲暇块来满足写申请。上述操作实现后,buffer-head 会被标记为提早调配(BH_DELAY),此时没有进行块调配。稍后,当页面通过 writepage() 或 writepages() 刷新到磁盘时,这些函数将遍历指定 Inode 中的所有脏页,汇集逻辑上间断的脏页,并尝试为所有标记为 BH_DELAY 的缓冲区头执行集群块调配,而后将页面提交给 bio 层。块调配实现后,未应用的保留块返回文件系统。

目前提早调配的实现,大多在 VFS 层实现,心愿 Ext2 和 Ext3 等多个文件系统可能受害于该个性。Ext4 为提早分配模式增加了新的地址空间操作,为提早调配提供了 write_begin()、write_end() 和 writepage() 的回调函数,并具备更新的块的调配、保留、查找性能。以后的 Ext4 提早调配仅反对 data=writeback 日志模式。未来,打算增加对 data=ordered 模式的提早反对。

细说 FLEX_BG 和 Inode 分配器

旧 Inode 分配器

Ext2/3 文件系统中的 Inode 分配器应用块组作为媒介,来确定新 inode 在存储介质上的地位。Ext2/3/4 文件系统被分成多个小块组,块组大小由单个位图能够解决的块数量决定。在 4 KB 块文件系统中,单个块位图能够解决 32768 个块,每个块组总共 128 MB。这意味着对于每 128 MB,就有元数据块(block/Inode 位图和 Inode table block)中断间断块,该间断块本可用于调配数据。

Orlov 目录 Inode 分配器 [6] 试图通过缩小在闲暇块计数较低的块组中,调配一个 inode 的机会来最大化取得大块调配的机会。Orlov 分配器还试图保护相干数据(即同一目录中的文件)的局部性。Orlov 分配器通过查看闲暇块、闲暇索引节点和块组中的目录数量比例,来找到目录索引节点的最佳地位。非目录的 Inode 调配由第二个分配器解决,该分配器从父目录所在的块组开始闲暇 Inode 搜寻,并尝试将具备雷同父 Inode 的 Inode 搁置在同一块组中。尽管思考到 Ext2/3/4 的块组设计,这种办法十分好,但它的确有一些限度:

  • 1 TB 的文件系统大概有 8192 个块组,在大量应用的文件系统上搜寻这么多块组,开销可能会变得很高。
  • Orlov 能够将目录 Inode 搁置在物理上远离其父目录的随机地位。
  • Orlov 计算寻找单个 128 MB 块组的计算成本很高。
  • 思考到硬盘寻道工夫在将来几年不会有太大的改善,同时容量和接口吞吐量会大幅度晋升,Orlov 分配器在改善数据局部性方面简直没有做任何动作。

当然,真正的问题不在于 Orlov 自身,而是块组大小对其施加的限度。解决此限度的一种解决方案是,实现多块位图。毛病是,在搜寻闲暇块以替换坏块时,解决其中一个位图或 Inode 表中的坏块之类的事件会变得非常复杂。一个更简略的解决方案是,解脱元数据须要位于文件系统块组中的概念。

FLEX_BG

简略地说,新的 FLEX_BG 打消了特定块组的位图和 Inode 表必须位于该块组的块范畴内的限度。咱们能够打消这个限度,次要是因为 e2fsprogs 是一个通过 fsck 查找谬误的弱小工具。尽管激活 FLEX_BG 性能标记自身不会扭转 Ext4 的任何行为,但该性能的确容许 mke2fs 用以前不可能的形式调配位图和 Inode 表。通过将位图和 Inode 表严密地调配在一起,能够构建一个大型虚构块组,从而绕过惯例块组的一些大小限度。

通过挪动元数据块,新的 extent 个性受害于新的元数据调配,否则会阻止存储介质上间断闲暇块的可用性。通过将这些块挪动到一个大型虚构块组的结尾,能够进步调配更大 extent 的可能性。此外,将多个块组的元数据间断存储在磁盘上,能够防止寻找元数据密集型工作负载,包含 e2fsck。

FLEX_BG Inode 分配器

既然咱们当初能够领有一个更大的块汇合,能够称之为块组,那么让内容利用这种能力显然是下一步。因为 Orlov 目录 Inode 分配器的一些设计决策取决于传统块组的大小限度,所以新的 inode 分配器须要采纳不同的技术,以便更好地利用磁盘元数据调配。新的 Inode 分配器与旧分配器的一些不同之处是:

  • 分配器总是在尝试调配另一个组之前,尝试将虚构块组填充到某个闲暇块比率。这样做是为了通过尽可能防止寻道来改善磁盘上的数据局部性。
  • 对目录的解决形式与惯例 Inode 的解决雷同。思考到这些虚构块组当初能够解决价值数 GB 的闲暇块,跨块组扩大目录不仅不能提供雷同的劣势,而且实际上可能会因为容许对绝对大量的数据进行更大的搜寻而侵害性能。
  • 分配器能够向后搜寻适合的块组。如果以后组没有足够的闲暇块,它能够会先尝试前一个组,以防空间被开释。
  • 分配器为组中的文件追加保留空间。如果应用了一个组中的所有块,那么将块追加到该组中的一个 Inode,可能意味着调配产生在存储介质内的较大偏移处,从而减少了寻道工夫。除非最初一个组已超过其保留比例,否则这个块预留不会被应用。

虚构组的大小始终是异样块组大小的二次方倍数,并在 mke2fs 工夫指定。大小存储在超级块中,用来管制如何构建内存中闲暇的 Inode 和块构造,算法应用这些块构造来确定虚构块组的利用率。因为咱们只在找到适合的虚构组时,才查看 Ext4 块组描述符,所以在大端序机器上,该算法比传统的 Orlov 分配器须要更少的端序转换。

与旧的分配器相比,这种新的 Inode 分配器的一个重点是,保护数据和元数据的局部性,以缩小寻道工夫。另一个十分重要的局部是,缩小调配开销。通过不同的形式解决目录 Inode,咱们从旧分配器中打消了很多复杂性,而更少数量的虚构块组使搜寻足够的块组更容易。

既然一组 Inode 表被视为单个大型 Inode 表,那么新的分配器还受害于 Ext4 中的另一个新个性。未初始化的块组在 Inode 表没有被应用时,将其标记为未初始化,因而在 fsck 时跳过读取这些 Inode 表,从而显著进步了 fsck 的速度。因为分配器仅在同一虚构组上的前一个表已满时,才应用 Inode 表,所以初始化的 Inode 表更少,从而须要加载的 Inode 表更少,fsck 工夫也更短。

性能后果展现

咱们应用 FFSB[4] 基准测试和一个配置文件,该配置文件执行小文件读取、写入、创立、追加和删除操作,这有助于模仿元数据沉重的工作负载。应用光纤通道磁盘阵列作为存储介质进行 FFSB 测试,具备 1 GB 疾速写入缓存。该基准测试是在一个蕴含 64 个打包组的 FLEX_BG 虚构块组中运行的,并将其与装置有 bot mballoc 和 delalloc 的惯例 Ext4 文件系统进行比拟。请留神,64 个压缩组合并不是每个硬件配置的最佳数量,但这个数字为可用硬件上的工作负载提供了十分好的总体性能。须要进一步钻研,以确定适宜特定硬件配置或工作负载的适合大小。

表二:FFSB 小元数据光纤通道(1 个线程)- 具备 64 个块组的 FLEX_BG

在表二中,单线程结果显示每秒操作吞吐量总体进步了 10%。在表三中,16 个线程结果显示,比惯例 Ext4 调配更好地进步了 18%。后果还表明,与失常调配相比,应用 FLEX_BG 分组时,从 1 到 16 个线程的可伸缩性进步了 5.6%。

表三:FFSB 元数据(16 个线程)FLEX_BG 有 64 个块组

为了查看新分配器对更简单的目录布局的整体成果,咱们应用了 Compilebench[5],它会生成指定数量的 Linux 内核树状目录,其中的文件代表理论内核树中的文件大小。在表四中,咱们看到应用分组和新的 Inode 分配器时,基准测试的总体后果更好。一个例外是“读取树”和“读取编译树”,它们显示的后果稍慢,这阐明元数据调配和 Inode 分配器还有肯定的改良空间。

表四:蕴含 64 个块组的 flex_BG

展望未来

Ext4 中元数据分组的概念依然处于起步阶段,还有很大的改良空间。咱们心愿通过查看元数据的布局来进步 Ext4 文件系统的性能。因为 FLEX_BG 个性的定义打消了元数据搁置的限度,这容许虚构组的实现是晦涩的,而不会就义向后兼容性。

其余值得摸索的优化是,将元数据搁置在虚构组的核心,而不是开始寻找最坏的状况。因为以后的实现只集中于 Inode 来操作块分配器,所以将来的实现能够更进一步,使各种块分配器具备 FLEX_BG 分组感知能力。因为组的大小取决于与磁盘自身相干的内容,所以让 mke2fs 能够更智能地依据媒介大小、媒介类型和 RAID 配置主动设置虚构组大小,这将有助于用户部署该个性。

打消文件系统大小限度的短期修复正在进行中。以后代码会在内存数据结构中存储了所有闲暇块和构建虚构块组的 Inode 总和。这意味着,如果数据结构超过页面大小,调配将失败,在这种状况下,咱们将在十分大的文件系统上复原到旧的分配器。尽管这是一种性能个性,但将所有这些信息存储在内存中,对于十分大的文件系统来说,可能有些过分。在 LRU 模式之上构建它能够打消这个限度并节俭内核内存。

✦  总结

从 Ext3 文件系统衍生出 Ext4 文件系统的次要动机是,突破绝对较小的文件系统大小限度。这满足了大文件、大 I/O 和大量文件的需要。为了将 Ext4 文件系统保护为桌面上的通用文件系统,确保 Ext4 文件系统在小文件上体现更好也很重要。

咱们曾经探讨了与 Ext4 文件系统中的块调配和 Inode 调配无关的工作,以及如何满足使 Ext4 成为桌面和服务器的高性能通用文件系统这两种互相抵触的要求。预调配、提早调配、组预调配和多个块调配的组合极大地缩小了 Ext3 文件系统中呈现的大文件调配时,呈现的碎片问题和小文件的局部性差问题。通过与 FLEX_BG 严密地调配位图和 Inode 表,能够构建一个大型虚构块组,从而减少了调配大块扩大的可能性,并容许 Ext4 文件系统更好地解决元数据密集型工作负载。将来的工作,包含对 ordered 模式日志和在线碎片整顿的提早调配的反对,将有助于将来缩小文件碎片问题。

原文起源:https://landley.net/kdocs/ols…

正文完
 0