For the complete documentation index, see llms.txt. This page is also available as Markdown.

文件系统基准测试的注意事项

众所周知,“在 Unix 中,一切皆文件”[14]。文档、可执行文件、硬盘、内存、资源使用统计乃至系统设置,都通过文件访问和修改。因此,文件系统是任何 Unix 衍生系统的基石,其性能与效率对整体系统速度至关重要。多年来,人们提出并开发了大量目标、设计与实现各异的文件系统。其中,持久化存储与检索数据的文件系统尤为重要。所有文件系统有一个共同点:都提供相同(POSIX)的 API。例如,使用符合 POSIX 的文件系统的应用,可以以可移植的方式创建、打开、读写文件;创建、列出并修改层次化目录树;访问和修改文件元数据等等。

运行中的应用会执行文件系统操作,并且常常需要等待操作完成。在许多生产系统中,应用等待文件系统操作所花的时间在总执行时间中占比最大。在这种情况下,我们说该应用是 I/O 受限的,提升其性能的最佳方式就是提升文件系统速度。但无法准确度量,就无法改进。因此,文件系统和存储基准测试对于计算机系统性能的渐进式改进和颠覆性改进都至关重要。

在实际场景中,基准测试常用于对比不同方案——例如在几款可用的文件服务器型号中做选择,或在不同的本地文件系统之间抉择。有时用户需要在完全不同的存储架构间做选择(例如本地存储对比共享存储)。随着新存储技术的出现,用户常常会想:升级到昂贵的 Flash 内存或 PCM 是否能将文件系统性能提升到满足自身需求的程度。可惜,现代文件系统有大量会强烈影响其性能的配置参数 [16];因此,选择最优的参数值可以缓解 I/O 瓶颈,避免或推迟代价高昂的升级 [4]。要回答这些和类似问题,就需要正确且公平地比较不同系统的性能。但这并非易事,主要因为有太多大大小小的细节需要考虑。

缺乏经验的用户(甚至专家)在基准测试方法上都会犯错 [18, 21]。本文将介绍正确评估基于文件系统的存储系统性能的重要原则和技巧。这里给出的指南源自我们在多种研究与工程项目中多年积累的文件系统与存储基准测试经验。

文件系统是 I/O 栈不可或缺的一环,I/O 栈至少包括 I/O 库、VFS 层、文件系统层、块层和硬件。对于网络文件系统,网络栈在性能中也扮演重要角色。当采用虚拟化时,I/O 栈的部分会在 VM 内复制,使总层数翻番 [20];类似地,RAID、LVM、可堆叠文件系统等存储虚拟化会增加更多层。每一层都有若干可选配置:所选的具体配置会极大影响 I/O 受限应用的整体性能。几乎不可能孤立地测量文件系统性能,即便可能,测量一个“中间件”层(如文件系统)而脱离它所依赖的软件、操作系统和硬件,得到的结果也没有意义。同一个文件系统(例如 FreeBSD 的 ffs [11])在不同环境中表现必然不同。即便是块层的预取大小这种细微差异,也能提升(或拖累)文件系统的性能。此外,由于软硬件的复杂性,即使单独增大两个参数的值都能提升性能,但同时增大两者却可能对性能产生负面影响。因此,实践中总是对整个 I/O 栈的所有层做基准测试,而不是孤立测试某一文件系统层。

我们将基准测试过程划分为四个主要步骤,如右图所示:(1) 系统配置,(2) I/O 负载生成,(3) 测量,(4) 分析。系统配置将系统的各个部分置于期望的状态(本文将在“系统配置”一节详述)。系统配置完成后,需要生成具有合适特征的 I/O 负载(见“I/O 负载生成”一节),并同步开始测量系统行为(见“测量”一节)。实际上,为了捕获系统初始和最终状态,在 I/O 负载生成之前和之后也需要测量。最后,分析、可视化测量结果并得出结论(见“分析”一节)。

基准测试是一个耗时、高度重复且迭代的过程;请注意图中的蓝色反馈箭头。当实验目标是比较几种备选配置或工作负载时,整个过程常常要对每种可能的设置重复多次。分析结果常常会暴露意料之外的现象,需要对配置、工作负载、测量或三者同时调整。例如,如果在分析阶段发现文件系统内存利用率低于预期,可能进一步揭示缓存大小上限设置得过低。然后可能决定用更大的缓存上限重复一遍实验。类似地,高强度的基准测试可能触发此前未见的缺陷,导致系统崩溃或暴露严重的“性能缺陷”,这就需要修改代码(有时还要修改设计),之后必须重跑整套基准测试。这种反馈循环有时不得不重复多次;不出意外,研究者发现花在这一基准测试循环上的时间远超首个系统原型的初始开发时间。

进入正文之前,我们有几条重要声明。首先,基准测试是一个充满开放争议和相互冲突观点的领域。我们表达自己的观点,希望这能推动关于如何正确开展存储评估的健康讨论。其次,和任何规则一样,基准测试规则也有例外。我们尽力覆盖最常见的场景,但我们给出的规则在大量合法场景中可以、甚至应该被改写。第三,我们关注的是性能,但性能并非决定哪个文件系统“更好”的唯一指标。所支持的功能集、采购成本和总拥有成本、功耗,只是影响存储方案决策的其它因素中的几个例子。第四,在实际中,实验者受限于实际时间约束(如软件发布周期、论文截止日期)。因此,我们既给出假设有无限时间的理想方法,也给出不够完美但更实用的技巧。我们认为,在充分理解所做假设的前提下,适度偏离既定的理想方法是可以接受的。

系统配置

系统配置是基准测试过程的第一步。尽管这一步对整个过程能否成功至关重要,但常常被不公平地忽视或视为琐碎之事。如果不详细了解系统配置,就无法正确分析结果、推导出普适结论,也无法在日后重复相同或衍生的实验。系统配置的三个主要目标是:(1) 摸清配置空间,(2) 自觉且可靠地将系统参数设置为所需值,(3) 收集详尽的配置描述以备日后参考。

大多数情况下,基准测试开始前并不清楚完整的配置空间。如果确实如此,应当仔细研究、理解并列出所有配置参数及其可能的取值。配置空间大致可分为两部分:只能手动修改的参数(例如通过安装不同的网络或存储设备),和易于通过程序修改的参数(例如文件系统类型或 pdflush 频率)。虽然某些参数不能通过程序设置,但往往可以通过程序读取(例如磁盘驱动器型号会出现在内核启动日志中)。即便预期参数在所有计划实验中保持不变,也应当记录下来。基准测试计划常常会变化。根据我们的经验,在计划不可避免改变时,记录完整的系统配置信息能节省大量时间。此外,了解硬件设置的细节会显著促进分析阶段的工作。具体而言,我们建议记录 HDD 和 SSD 的容量、型号、速度和特性(例如是否支持 TRIM 命令,SSD 的并行度等)、网卡型号和速度、硬件 RAID 控制器型号和设置(例如读写缓存大小、模式)、CPU/核心数量、型号和速度、内存容量和拓扑、系统 BIOS 设置等等。某些软件参数也保持静态且不易更改,但仍应记录(例如内核、发行版和库的版本)。配置采集应尽可能自动化(例如使用 shell 脚本)。

可通过程序修改的参数,应在每次实验前设置为合适的值。这能确保在实验之间(有时跨越数周)系统参数不会被意外改动。许多配置参数有默认值。例如,格式化文件系统时通常不需要指定块大小或 inode 大小。我们强烈建议永远不要相信默认值,因为它们随环境而异。如果假定各处默认值相同,就有可能在不知情的情况下比较了两套不同的配置。因此,请显式设置所有参数值。如前所述,这些规则不应仅限于文件系统设置。所有 I/O 栈参数(例如 pdflush 频率、脏内存高/低水位)都应当显式设置。如果使用了软件卷管理器或 iSCSI,则相应的设置也需要检查和设置。我们还建议收集运行中进程的列表,并验证没有可能干扰实验的意外进程在运行(例如 cron 作业、后台守护进程)。

设置完所有参数值后,我们建议将它们全部读回来一遍。这是一种额外的安全措施,确保所有设置确实生效,配置命令中没有出错。我们认为有必要在每次实验的开头和结尾各读一次参数,以确保参数在实验过程中没有发生变化。保存所有命令的输出,并将这些配置与结果一并存储。

一些现代存储系统支持去重、压缩、加密等高级特性。了解这些特性很重要。例如,如果支持压缩,那么在 I/O 负载生成阶段写入具有刻意选定压缩比的数据就很重要。有时可能决定临时禁用某些高级特性以简化结果分析,或确定某个特性的性能代价与效率。

在现代基础设施中,硬件常常是共享的(例如通过 SAN 连接的 JBOD 或 NFS 服务器)。其它用户的流量可能干扰实验,导致结果对环境敏感,并损害可复现性。只要可能,应确保实验期间没有他人使用共享资源。例如,可以禁止远程登录到机器,并将 NFS 挂载限定在一组特定节点上。如果无法从技术上限制对共享资源的访问,可以请其它用户在你的实验期间不要使用这些资源。虽然这不是有保证的方法,但仍能提高结果不受干扰的可能性。

专业人士常采用多台相同机器并行以加快实验。例如,可以将一组实验拆分,一部分在一台机器上执行,另一部分在另一台机器上运行。理想情况下,这能让实验快一倍完成。但使用两台机器并不理想,因为即便看似相同的机器,性能也不完全一致。事实上,有研究表明现代 HDD 在同一型号产品线内性能差异可达 20% [10]。然而,由于实际时间约束,常常不得不使用多台机器。在这种情况下,我们建议将完全相同的实验实例分散到不同节点上,然后报告平均值并附带方差指标(例如标准差)。这样,机器之间的差异就被纳入性能数据(而不是无意中为工作负载或配置之间的性能差异添砖加瓦)。请注意,这种方法的好处是结果描述的不是某一台具体机器上的系统性能,而是一批“相同”机器上的性能,更具普适性,价值更高。

另一种常见的加快实验的方式是人为限制 RAM 大小,从而使用更小的数据集,同时仍能产生充足的 I/O 活动(数据集大小详见“I/O 负载生成”一节)。这种情况下,初始数据集创建和缓存预热阶段都更快。隐含假设是:如果 RAM 与数据集之比保持不变,那么更大数据集(和更大 RAM)下的性能也保持不变。从逻辑上讲得通,但我们尚未见到任何研究验证过这一假设。因此,如果时间允许,最好不要人为限制 RAM 大小,使用完整的数据集。在时间受限时,我们建议确保限制 RAM 大小后,每个 CPU 节点仍可访问相同数量的 DRAM 插槽(仅在 NUMA 节点中相关)。

每次实验前,需将系统配置为与系列中其它实验完全相同的状态——当然,由实验目标决定的差异除外(例如比较一种配置与另一种配置)。配置步骤的设计应使系统在实际工作负载运行前回到同一起点。对于文件系统基准测试,我们建议每次实验前都格式化文件系统。仅重新挂载文件系统是不够的,因为前一次实验中文件系统的使用历史会影响后续实验的性能。挂载文件系统后,有时需要将文件系统老化至真实(但可复现)的状态,因为文件系统性能会随时间下降 [1]。如果无法进行老化(例如耗时太长或工具不可用),使用空文件系统是替代方案。至少,我们建议用文件系统在生产中预期存储的数据量将其填满,因为许多存储设备在写入更多数据时性能会下降。例如,HDD 在外圈磁道(先填充的磁道)吞吐量更高,因为外圈线速度更高。SSD 则使用未写入空间作为预擦除块,因此利用率越高,性能也越下降。事实上,我们建议在实验前完全覆写 SSD,以触发长期运行的生产系统中典型的垃圾回收。对 SSD 执行 TRIM 命令可能没有意义,因为充其量它只会将 SSD 恢复到最优性能状态,而这通常不是真实评估的目标。更糟的是,SSD 在每次实验前可能处于不同状态,因为 TRIM 可以异步执行,无法确定闪存转换层(FTL)何时真正擦除所有块。

值得一提的是,现代系统通常本身就有随机性。例如,某些文件系统随机分配磁盘块,以在文件系统生命周期内提供一致的性能 [15]。在这种情况下,几乎不可能将系统恢复到完全相同的状态。每次配置过程都会产生略有不同的设置。但这样的差异完全没问题。它们要么不会显著影响性能数据,要么如果确实影响,用户就会了解到系统对初始状态的敏感性(例如报告更高的标准差)。此后,可以判断这对特定环境是否可接受的性能方差。

在配置及后续步骤中,重要的是不要遗漏工具或系统返回的任何错误。如果任何单个命令以非零状态退出,或内核或系统日志中出现错误,我们建议立即停止实验。错误修复或被确认无关后,应从头恢复运行。

对于分布式文件系统,涉及多台服务器和客户端,上述步骤需要每个节点重复执行。

I/O 负载生成

成功配置目标系统后,下一步是生成具有所需特征的 I/O 负载,我们称之为 I/O 工作负载。此过程中用户需要牢记的两件最重要的事是:(1) 尽可能详细地理解基准测试或应用做了什么,(2) 仔细思考如何运行基准测试或应用。下面我们介绍生成文件系统负载的四种常见方法——微基准、宏基准、I/O 追踪和应用级基准——每种方法适用于特定场景 [21]。

  • 微基准。这类基准测试旨在执行少数(通常一两种)文件系统操作——例如测量文件系统每秒能完成多少次创建操作。当目标是测量系统中小改动的影响、(之后)更好地理解宏基准的结果,或用户想隔离系统特定部分的影响时,这类基准测试很有用。微基准的结果如果能与其它类型基准的结果一起呈现,会更有价值、更有意义。常用的微基准示例包括 fio [6]、iozone [3] 和 Filebench 的部分 personality [5]。

  • 宏基准。宏基准的目标是估计系统部署到生产环境后的性能。这类基准执行多种文件系统操作,通过观察和特征化真实工作负载然后模拟它们来设计。宏基准示例包括 Filebench 的 Web/Mail/File personality [5] 和 SPEC SFS®。

  • I/O 追踪。存储开发者很早就认识到,在复杂情况下简单的计数器不足以分析系统行为,因此添加了记录系统中每个操作的能力。I/O 追踪是在特定系统上捕获的、带时间戳的文件系统或块级操作记录的集合。在一个系统上收集到追踪后,可以在其它系统上重放以评估其性能。追踪重放可以提供存储性能的准确估计,但用户仍需确保所用追踪确实代表真实工作负载。例如,追踪应覆盖较长时间段,以尽可能捕获更多使用模式。

重放 I/O 追踪有几种方法,引发了关于哪种重放方法最合适的争论 [21]。有些按原始时间重放追踪。然而,追踪通常是在较旧较慢的系统上收集的,因此使用原始时间不足以给较新较快的存储施加压力。另一种方法是尽可能快地重放追踪,忽略时间,并固定未完成请求的总数。在这种情况下,请求之间的相互依赖被忽略,结果可能与实际不符。最后,作为折中方案,可以按固定加速因子重放追踪,并限制同时未完成请求的最大数量。使用追踪重放进行评估时,我们建议使用上述所有方法并得出适当结论。据我们所知,目前没有广泛可用的文件系统追踪重放工具;btreplay 工具可用于重放块级追踪。

  • 应用级基准。前述基准只是模拟真实应用。应用级基准则通过在目标系统上部署真实应用来测试系统。基准随后模拟用户在现实中操作这些应用的方式。例如,TPC-C 基准 [22] 需要部署真实数据库软件,并以代表复杂 OLTP 应用环境的方式执行,描绘真实批发供应商的活动。

现实生活中观察到的以及基准产生的 I/O 工作负载,通常用一组通用指标来特征化,如操作比率、I/O 大小分布、并行度、顺序性和数据集大小。这种特征化背后的前提是,存储系统的性能主要取决于宏观统计特性,而非工作负载的微小细节 [19]。

例如,操作比率是每种文件系统操作类型(如读、写、创建)在总体混合中所占的百分比。类似但更粗略的特征化区分元数据密集型(命名空间操作占比高)与数据密集型工作负载。文件系统性能通常对此特性相当敏感,因为命名空间管理操作的设计和实现与数据管理截然不同。在评估中,通常需要使用产生的工作负载特性接近目标环境中所观察到特性的基准。

工作负载的一个特别重要的属性是数据集大小。有些工作负载可以将其数据集完全放入 RAM,此时底层存储不影响文件系统性能。但更常见的是,数据集大小大于文件系统缓存大小,因此内存和存储子系统都会被使用。我们建议将数据集大小设为可用 RAM 大小的几倍。更好的做法是用不同的数据集大小做实验,保持其它所有工作负载特性不变。我们要强调,文件系统性能对数据集和 RAM 大小可能非常敏感。我们曾证明,数据集大小仅增加 6MB 就可能导致吞吐量下降近 10 倍 [18]。

在许多生产部署中,工作负载不会使系统达到峰值性能。换句话说,提交到文件系统的请求之间有大量空闲时间。评估存储系统时,可能决定尊重现实的空闲时间,观察系统在非压力场景下的行为(例如测量传入请求速率较小时的请求延迟)。另一种方法是观察系统在最高负载下的行为,从而测量系统的峰值性能。我们建议将负载从适中到最高水平变化进行评估,并报告这一连续区间内所有点的性能。

近年来,工作负载的若干非传统方面变得重要。如果存储系统支持去重或压缩,基准应生成具有适当压缩或去重级别的内容。许多较旧的基准向文件系统写入零或任意数据,两者都不能正确评估系统。需要选择特定环境中预期的压缩比——例如,如果目标存储系统用于存储文档,典型压缩比在 3 到 5 倍范围内 [9]。较新版本的 fio、Filebench 和其它基准支持压缩特性。DEDISbench [13] 是用于去重系统的 I/O 基准,它将重复内容的分布作为输入之一。

基准测试的下一步是理解何时终止 I/O 负载的条件。指定停止条件有两种方法:基于时间和基于作业。基于时间的方法指定基准运行的固定持续时间。这类示例包括运行压力测试以查看 Web 服务器在一天高峰时段能处理多少请求。相比之下,基于作业的方法指定每次基准运行需完成的工作量。例如,测试在大数据系统中排序 1TB 文本文件的速度时,基于作业的方法比基于时间的方法更方便也更有意义。注意,在这种情况下,运行时间实际上成为反映系统性能的相关指标。实践中两种方法都有效,选择哪种取决于用例。

在决定实验运行多长时间时,用户还需要考虑系统操作的典型周期,如缓存刷新、日志回卷、大压缩和小压缩等。基准至少应覆盖最长操作周期的多个迭代,以评估系统行为的所有模式。此外,一些基准测试工具在模拟工作负载的实际运行前有预热阶段,让系统达到稳态。预热阶段通常不收集指标。我们认为不必将预热阶段区别对待,因为了解预热期间系统在性能和其它指标方面的表现往往很重要。因此,用户应将预热视为运行的一部分,定期收集所有测量数据,之后如需要,可以丢弃实验预热阶段收集的数据。

基准运行完成后,有人建议执行 fsync 操作。但我们认为这是多余的步骤,因为它实际上取决于真实工作负载的具体特性。如果真实工作负载末尾不会发生 fsync 操作,就没有必要在基准测试后添加 fsync。事实上,如果工作集大小和基准持续时间足够大,脏数据刷新应在运行期间发生多次,并包含在性能结果中。

最后但同样重要的是,我们鼓励避免使用自制的存储基准。这会使任何结果验证、复现复杂化,并损害其可信度。

测量

生成工作负载的同时,需要收集既测量系统性能、又在更广泛意义上描述系统行为的指标。测量作为结果分析的输入——基准测试的最后一步。测量的数量和质量在很大程度上决定结果分析的速度和效率。

文件系统基准测试的度量学有两个主要问题:(1) 测量什么,(2) 如何测量。第一个问题是关于我们需要收集哪些重要指标以促进后续分析;第二个问题是关于如何准确高效地测量这些相关指标。两个问题的答案都不是绝对的,很大程度上取决于所用存储设备、文件系统类型、工作负载和分析目标。本节讨论帮助回答这些问题的一般指导原则。

测量什么

考虑到现代文件和存储系统的复杂性,识别相关指标的任务可能具有挑战性;了解“好”指标的常见特性可以简化此任务。好指标有四个决定性特征:(1) 信息丰富,(2) 定义明确,(3) 可量化,(4) 简单。由于指标的目的是帮助工程师和研究人员理解系统,每个指标都应足够信息丰富,以促进一项或多项分析任务,包括健全性检查、环境监控、系统行为分析、性能评估和故障排除。信息丰富的指标通常是系统环境(如温度、网络负载)、资源利用率(如 CPU 或内存使用)、系统性能(如吞吐量、延迟)或系统事件(如缺页、中断、新块分配)的清晰指示。

好指标还应定义明确,无任何歧义。定义明确的指标应有清晰的收集上下文。同一类型的指标在不同上下文中可能显著不同。例如,在使用网络文件系统(NFS)的设置中,应用层测量的吞吐量(以 MB/sec 为单位)不等于 NFS 客户端层测量的吞吐量,因为客户端有页缓存;应用层吞吐量也不匹配 RPC 层测量的吞吐量,因为客户端有 FSCache [8] 等持久缓存。此外,NFS 服务器块层测量的吞吐量是另一个完全不同的指标。

定义明确的指标还应有清晰且有意义的边界,标记指标的起点和终点。许多基准测试研究在这方面失败,例如选择一个多少有些任意的预热阶段,并只报告预热后的性能指标。问题在于固定的预热阶段不一定有意义:预热可能旨在填充缓存,但固定预热阶段后缓存满的程度在不同工作负载中不同。那么看似合理的预热将导致报告的结果取决于未知且可能不同的初始缓存状态。如“I/O 负载生成”一节中所述,更好的替代方案是在实验最开始(预热前)标记指标起点,并测量直到工作完成。

可量化是好指标的另一个重要特征。定量指标往往比定性指标更准确、更可复现;定量指标也比定性指标带来更客观的分析。正如精确测量了绝对零度的著名物理学家开尔文勋爵所说:“当你测量你所谈论的事物并用数字表达时,你对它有所了解;但当你不能用数字表达时,你的知识是贫乏且不令人满意的。”例如,将写入空页缓存时的吞吐量描述为“突发式”,不如“1GB/sec 的吞吐量在 5 秒后降至 80MB/sec”清晰。

好指标的第四个特征是简单,这使指标易于测量。更简单的指标也使测量后的分析更直观、更不易出错。

现在我们了解了寻找好指标时应关注哪些理想特性,讨论如何识别相关指标。测量单个性能指标是糟糕的做法;我们为实验收集的指标应足够全面,以进行实验后广泛的分析任务。因此,我们应在以下所有类别中收集指标:

  • 性能指标。这些指标如吞吐量和延迟,是性能的直接指示,因此最为重要。可能有多个吞吐量指标和多个延迟指标。例如在 NFS 中,存储和网络栈的不同级别有 ops/sec 和 MB/sec 吞吐量指标;也有终止于不同层的多个延迟指标(如页缓存命中的延迟、FSCache 命中的延迟)。

  • 资源利用率。CPU、内存、存储 I/O 和网络的使用也是重要指标。它们是系统效率的直接指示,有助于理解系统行为和故障排除。

  • 设置指标。我们应测量验证设置并作为评估基线的指标。例如,缓存设备是否确实比主存储设备快得多,100% 缓存命中率下的最大可能加速是多少?如可能,我们应自己测量设置指标,因为厂商提供的指标往往过于简单或过于乐观,不可信。

  • 系统特定指标。例如支持这些特性的系统报告的压缩和去重比率。

  • 外部事件指标。这些指标如外部客户端的请求速率,在我们无法完全控制的基准测试环境中尤为重要。

  • 环境指标。如服务器机器的温度、存储网络的拥塞程度。

如何测量

知道要测量的指标后,下一步是进行测量。好的测量应具有以下特征:

  • 准确性。准确意味着指标的测量值接近指标的真实值。准确的测量构成正确决策的基础。

  • 精度和稳定性。精确意味着同一指标的多次测量结果彼此接近。高精度使我们对测量的一致性和可复现性有信心。

  • 效率。效率很重要,可确保我们的测量不会引入过多系统负载而扭曲系统性能。

  • 自动化。自动化测量更可复现,更不易受人为错误引起的不确定性影响。

测量文件和存储系统指标时,我们还推荐以下实践:

  • 多次重复实验和测量。多次运行使我们对精度有信心;对于变化很大的指标,多次运行(尤其是以箱线图或 CDF 显示时)能更真实地描述指标的范围。例如,网络延迟的分布比单一延迟更能说明网络的动态特性和存储的多层结构。

  • 实验期间定期测量指标,而非仅在末尾测量一次。系统是动态的,指标在运行期间常会变化。以时间序列图显示时,频繁测量可以捕获指标的动态并过滤随机噪声。根据我们的经验,测量间隔 10 秒可提供足够的粒度而不会造成过多开销。

  • vmstat、iostat 和 nfsstat 等工具不是测量的原始来源。这些工具从 /proc 文件系统读取数字,执行额外计算,然后将结果打印给用户。然而,这些计算可能并不简单,加上标注不清可能导致错误结论。一个常见例子是 iostat 中的服务时间指标,它对旧 HDD 有效,但对高度并行的 SSD 几乎没有意义 [2, 12]。因此,如可能,我们建议坚持使用原始数据源,在分析阶段自行计算。

  • 为每次测量记录通用时间戳。这些时间戳可以帮助协调不同子系统(如存储和网络、客户端和存储服务器)的事件。当实验涉及多台机器时,使用网络时间协议(NTP)同步时间很重要。

  • 通过有无测量的实验确保测量的性能惩罚可忽略。

  • 将测量与实验中使用的配置和工作负载描述一起保存。让每个实验的文件夹完全自包含会很方便。

分析

分析步骤要么达到整个评估的最终目标,要么指导额外实验的设计(见第 15 页图中的反馈箭头)。本节分享几个我们发现有用的分析实践。

  • 格式化。测量常常以五花八门、不利于后处理的格式收集——例如 iostat 和 vmstat 工具的输出截然不同,无法直接输入 Gnuplot 或电子表格工具。我们发现先将所有测量格式化为某种通用结构化格式很方便。根据我们的经验,CSV 格式提供最佳通用基础:大多数分析或可视化工具都接受,人可读,程序可解析。CSV 格式文件也便于与可能使用不同工具集的其它相关方共享。我们通常使用 CSV 文件,第一列包含时间戳,其余列包含相应的测量值。

运行许多实验后,评估者会得到许多实验结果。一致的文件命名约定和目录结构非常有用。这不仅简化了人类对结果的浏览,还允许我们轻松地对所有实验使用相同的分析和可视化脚本。

  • 可视化。收集了这么多数字后,不用图形总结数字就实际上不可能理解它们。我们发现 Gnuplot 和 Python 的 matplotlib 是强大的工具,易于脚本化;它们极大地加速了许多实验的绘图。

我们总是建议从时间序列图开始——X 轴显示时间,Y 轴显示某个测量指标的图形。例如,吞吐量时间序列图使我们能快速了解整个运行期间性能是否稳定。如果不稳定(例如由于运行开始时的缓存效应),在报告平均吞吐量时,可能只考虑缓存变热后的吞吐量。类似地,绘制内存利用率随时间的变化,可以确认缓存变满的时间点。在许多实验中,可以看到由于周期性缓存刷新或段压缩导致的周期性性能下降。

在准备比较多个独立实验的图形时,显示每个指标的可变性很重要。具体而言,不要使用每个实验只有单个平均值的条形图,箱线图在相同空间中显示更详细的统计信息(均值对中位数、异常值、上下四分位数等)。

  • 健全性检查。分析的首要任务之一是验证测量总体上合理。例如,如果应用层的吞吐量是 HDD 带宽的几倍(而根据你的实验设置,数据集不适合放入 RAM),那么实验可能有问题。可能是数据集比预期小得多、数据被完全去重或其它原因。另一个例子是,在为数据密集型设计的实验中观察到许多元数据操作。特别需要关注的是结果“好得难以置信”时,因为它们往往不是。

健全性检查的另一项任务是验证所有日志不包含错误和警告消息。

  • 开销。我们常看到人们将性能下降称为开销——例如,如果启用去重后吞吐量从 100MB/sec 降到 80MB/sec,有时会说去重的开销是 20%。然而,这不准确。开销是关于资源利用率的,如 CPU 周期、内存使用、I/O 带宽,而非性能 [7]。在上面的例子中,I/O 带宽使用可能增加了一倍(例如用于将去重索引引入 RAM),因此实际 I/O 开销是 100%。相反的例子是,启用某个特性后性能提升 50%。只报告特性将性能提高 1.5 倍的事实不是好做法。事实上,CPU 利用率很可能从 25% 增长到 75%,这意味着该特性的 CPU 开销是 300%。如果开销过高,性能提升往往不可接受,因此分析应同时报告性能改进和资源利用率。

  • 性能。文件系统性能的两个基本指标是吞吐量和延迟。根据上下文,吞吐量可定义为 IOPS(每秒 I/O 操作数)或 MB/sec。我们建议始终从 IOPS 开始,因为这是更通用、更不含糊的指标,同样适用于元数据和数据操作。根据操作混合和 I/O 大小,不同的 IOPS 可不同地转换为 MB/sec。对于一种工作负载,高 IOPS 可能仍意味着低 MB/sec(元数据操作或小 I/O 大小的随机 I/O),而对另一种工作负载,低 IOPS 可能转换为高 MB/sec(大的多 MB 写操作)。分析 IOPS 指标后,可根据需要将其转换为 MB/sec。

注意,对于某些软件,高吞吐量重要,而对于另一些,低延迟更有价值。单线程系统(始终有一个请求在处理中)的平均延迟可计算为 IOPS 的倒数。然而,存储栈大多是多线程的,同时提交多个请求时吞吐量会成倍增加。但如果提交过多请求,延迟可能因排队而增长。我们建议分析吞吐量如何依赖延迟——例如,将吞吐量放在 X 轴,平均延迟放在 Y 轴,可以看到系统延迟在哪个吞吐量下仍可接受。监控系统队列通常有助于更好地理解此行为。

结论

存储硬件、软件和工作负载种类繁多。每次构建新系统或升级旧系统时,都需要决定使用哪种存储设置。功能之后,性能是第二重要的系统特性。虽然容易确定存储层提供的功能是否足够,但要确保性能达到所需水平则困难得多。存储基准测试是致力于回答这一复杂问题的学科。然而,人们对存储进行基准测试已有很长时间,我们仍看到大量不良实践:不清晰的配置、不合适的工作负载、选择不当的指标和错误的分析。本文介绍了我们多年来艰难学到的一些技巧和技术。我们希望这里介绍的信息对读者有用,也希望并鼓励社区在未来使用并发布更多高质量的存储性能评估。


Erez Zadok 于 2001 年在哥伦比亚大学获得计算机科学博士学位。他主持纽约州立大学石溪分校计算机科学系文件系统与存储实验室(FSL),并于 2001 年加入该校任教。目前的研究方向包括文件系统与存储、操作系统、能效、性能与基准测试、安全和网络。他曾获得纽约州立大学校长卓越教学奖、美国国家科学基金会(NSF)CAREER 奖、两次 NetApp 教师奖和两次 IBM 教师奖。

Ming Chen 在中国北京航空航天大学获得计算机科学学士和硕士学位。他是纽约州立大学石溪分校的五年级博士生,在文件系统与存储实验室(FSL)师从 Erez Zadok 教授。研究方向包括分布式存储系统和云计算系统的分析、设计与实现。

Vasily Tarasov 是 IBM Almaden 研究中心研究员,2013 年在纽约州立大学石溪分校获得博士学位。研究兴趣包括系统性能分析、分布式系统的设计与实现,以及超高速存储设备的高效 I/O 栈。他维护并大量贡献于流行的 Filebench 基准测试框架。

Zhen Cao 在中国复旦大学获得软件工程学士学位。他是纽约州立大学石溪分校的三年级博士生,在文件系统与存储实验室(FSL)师从 Erez Zadok 教授。研究兴趣包括复杂存储系统的基准测试和自动调优。

最后更新于