草庐IT

JuiceFS 性能评估指南

JuiceFS 2023-03-28 原文

JuiceFS 是一款面向云原生环境设计的高性能 POSIX 文件系统,任何存入 JuiceFS 的数据都会按照一定规则拆分成数据块存入对象存储(如 Amazon S3),相对应的元数据则持久化在独立的数据库中。这种结构决定了 JuiceFS 的存储空间可以根据数据量弹性伸缩,可靠地存储大规模的数据,同时支持在多主机之间共享挂载,实现跨云跨地区的数据共享和迁移。

JuiceFS 在运行过程中, 可能会因为硬件软件差异, 系统配置不同, 文件大小等原因导致实际的性能表现会有所不同。之前分享过[如何利用 JuiceFS 的性能工具做分析和调优]本文我们将更进一步介绍如何对 JuiceFS 进行准确的性能评估,希望能帮到大家。

前言

在进行性能测试之前,最好写下该使用场景的大致描述,包括:

  1. 对接的应用是什么?比如 Apache Spark、PyTorch 或者是自己写的程序等
  2. 应用运行的资源配置,包括 CPU、内存、网络,以及节点规模
  3. 预计的数据规模,包括文件数量和容量
  4. 文件的大小和访问模式(大文件或者小文件,顺序读写或者随机读写)
  5. 对性能的要求,比如每秒要写入或者读取的数据量、访问的 QPS 或者操作的延迟等

以上这些内容越清晰、越详细,就越容易制定合适的测试计划,以及需要关注的性能指标,来判断应用对存储系统各方面的需求,包括 JuiceFS 元数据配置、网络带宽要求、配置参数等。当然,在一开始就清晰地写出上面所有的内容并不容易,有些内容可以在测试过程中逐渐明确,但是在一次完整的测试结束时,以上使用场景描述以及相对应的测试方法、测试数据、测试结果都应该是完整的

如果上面的内容还不明确,不要紧,JuiceFS 内置的测试工具可以一行命令得到单机基准性能的核心指标。同时本文还会介绍两个 JuiceFS 内置的性能分析工具,在做更复杂的测试时,这两个工具能帮你简单清晰的分析出 JuiceFS 性能表现背后的原因。

性能测试快速上手

以下示例介绍 JuiceFS 内置的 bench 工具的基本用法。

环境配置

  • 测试主机:Amazon EC2 c5.xlarge 一台
  • 操作系统:Ubuntu 20.04.1 LTS (Kernel 5.4.0-1029-aws)
  • 元数据引擎:Redis 6.2.3, 存储(dir)配置在系统盘
  • 对象存储:Amazon S3
  • JuiceFS version:0.17-dev (2021-09-23 2ec2badf)

JuiceFS Bench

JuiceFS bench 命令可以帮助你快速完成单机性能测试,通过测试结果判断环境配置和性能表现是否正常。假设你已经把 JuiceFS 挂载到了测试机器的 /mnt/jfs 位置(如果在 JuiceFS 初始化、挂载方面需要帮助,请参考快速上手指南,执行以下命令即可(推荐 -p 参数设置为测试机器的 CPU 核数):

$ juicefs bench /mnt/jfs -p 4

测试结果会将各项性能指标显示为绿色,黄色或红色。若您的结果中有红色指标,请先检查相关配置,需要帮助可以在 GitHub Discussions 详细描述你的问题。

JuiceFS bench 基准性能测试的具体流程如下(它的实现逻辑非常简单,有兴趣了解细节的可以直接看源码

  1. N 并发各写 1 个 1 GiB 的大文件,IO 大小为 1 MiB
  2. N 并发各读 1 个之前写的 1 GiB 的大文件,IO 大小为 1 MiB
  3. N 并发各写 100 个 128 KiB 的小文件,IO 大小为 128 KiB
  4. N 并发各读 100 个之前写的 128 KiB 的小文件,IO 大小为 128 KiB
  5. N 并发各 stat 100 个之前写的 128 KiB 的小文件
  6. 清理测试用的临时目录

并发数 N 的值即由 bench 命令中的 -p 参数指定。

在这用 AWS 提供的几种常用存储类型做个性能比较:

  • EFS 1TiB 容量时,读 150MiB/s,写 50MiB/s,价格是 $0.08/GB-month
  • EBS st1 是吞吐优化型 HDD,最大吞吐 500MiB/s,最大 IOPS(1MiB I/O)500,最大容量 16TiB,价格是 $0.045/GB-month
  • EBS gp2 是通用型 SSD,最大吞吐 250MiB/s,最大 IOPS(16KiB I/O)16000,最大容量 16TiB,价格是 $0.10/GB-month

不难看出,在上面的测试中,JuiceFS 的顺序读写能力明显优于 AWS EFS,吞吐能力也超过了常用的 EBS。但是写小文件的速度不算快,因为每写一个文件都需要将数据持久化到 S3 中,调用对象存储 API 通常有 10~30ms 的固定开销。

注 1:Amazon EFS 的性能与容量线性相关参考(AWS 官方文档),这样就不适合用在小数据量高吞吐的场景中。

注 2:价格参考 AWS 美东区(US East, Ohio Region),不同 Region 的价格有细微差异。

注 3:以上数据来自 AWS 官方文档,性能指标为最大值,EBS 的实际性能与卷容量和挂载 EC2 实例类型相关,总的来说是越大容量,搭配约高配置的 EC2,得到的 EBS 性能越好,但不超过上面提到的最大值。

性能观测和分析工具

接下来介绍两个性能观测和分析工具,是 JuiceFS 测试、使用、调优过程中必备的利器。

JuiceFS Stats

JuiceFS stats 是一个实时统计 JuiceFS 性能指标的工具,类似 Linux 系统的 dstat 命令,可以实时显示 JuiceFS 客户端的指标变化(详细说明和使用方法见性能监控文档)。执行 juicefs bench 时,在另一个会话中执行以下命令:

$ juicefs stats /mnt/jfs --verbosity 1

结果如下,可以将其与上述基准测试流程对照来看,更易理解:

其中各项指标具体含义如下:

  • usage
    • cpu: JuiceFS 进程消耗的 CPU
    • mem: JuiceFS 进程占用的物理内存
    • buf: JuiceFS 进程内部的读写 buffer 大小,受挂载项 --buffer-size 限制
    • cache: 内部指标,可不关注
  • fuse
    • ops/lat: FUSE 接口每秒处理的请求个数及其平均时延(单位为毫秒,下同)
    • read/write: FUSE 接口每秒处理读写请求的带宽值
  • meta
    • ops/lat: 元数据引擎每秒处理的请求个数及其平均时延(请注意部分能在缓存中直接处理的请求未列入统计,以更好地体现客户端与元数据引擎交互的耗时)
    • txn/lat: 元数据引擎每秒处理的写事务个数及其平均时延(只读请求如 getattr 只会计入 ops 而不会计入 txn)
    • retry: 元数据引擎每秒重试写事务的次数
  • blockcache
    • read/write: 客户端本地数据缓存的每秒读写流量
  • object
    • get/get_c/lat: 对象存储每秒处理读请求的带宽值,请求个数及其平均时延
    • put/put_c/lat: 对象存储每秒处理写请求的带宽值,请求个数及其平均时延
    • del_c/lat: 对象存储每秒处理删除请求的个数和平均时延

JuiceFS Profile

JuiceFS profile 一方面用来实时输出 JuiceFS 客户端的所有访问日志,包含每个请求的信息。同时,它也可以用来回放、统计 JuiceFS 访问日志,方便用户直观了解 JuiceFS 的运行情况(详细的说明和使用方法见性能诊断文档)。执行 juicefs bench 时,在另一个会话中执行以下命令:

$ cat /mnt/jfs/.accesslog > access.log

其中 .accesslog 是一个虚拟文件,它平时不会产生任何数据,只有在读取(如执行 cat)时才会有 JuiceFS 的访问日志输出。结束后使用 Ctrl-C 结束 cat 命令,并运行:

$ juicefs profile access.log --interval 0

其中 --interval 参数设置访问日志的采样间隔,设为 0 时用于快速重放一个指定的日志文件,生成统计信息,如下图所示:

从之前基准测试流程描述可知,本次测试过程一共创建了 (1 + 100) * 4 = 404 个文件,每个文件都经历了「创建 → 写入 → 关闭 → 打开 → 读取 → 关闭 → 删除」的过程,因此一共有:

  • 404 次 create,open 和 unlink 请求
  • 808 次 flush 请求:每当文件关闭时会自动调用一次 flush
  • 33168 次 write/read 请求:每个大文件写入了 1024 个 1 MiB IO,而在 FUSE 层请求的默认最大值为 128 KiB,也就是说每个应用 IO 会被拆分成 8 个 FUSE 请求,因此一共有 (1024 * 8 + 100) * 4 = 33168 个请求。读 IO 与之类似,计数也相同。

以上这些值均能与 profile 的结果完全对应上。另外,结果中还显示 write 的平均时延非常小(45 微秒),而主要耗时点在 flush。这是因为 JuiceFS 的 write 默认先写入内存缓冲区,在文件关闭时再调用 flush 上传数据到对象存储,与预期吻合。

其他测试工具配置示例

Fio 单机性能测试

Fio 是业界常用的一个性能测试工具,完成 JuiceFS bench 后可以用它来做更复杂的性能测试。

环境配置

与 JuiceFS Bench 测试环境一致。

测试任务

执行下面四个 Fio 任务,分别进行顺序写、顺序读、随机写、随机读测试:

# Sequential
$ fio --name=jfs-test --directory=/mnt/jfs --ioengine=libaio --rw=write --bs=1m --size=1g --numjobs=4 --direct=1 --group_reporting
$ fio --name=jfs-test --directory=/mnt/jfs --ioengine=libaio --rw=read --bs=1m --size=1g --numjobs=4 --direct=1 --group_reporting

# Random
$ fio --name=jfs-test --directory=/mnt/jfs --ioengine=libaio --rw=randwrite --bs=1m --size=1g --numjobs=4 --direct=1 --group_reporting
$ fio --name=jfs-test --directory=/mnt/jfs --ioengine=libaio --rw=randread --bs=1m --size=1g --numjobs=4 --direct=1 --group_reporting

参数说明:

  • --name:用户指定的测试名称,会影响测试文件名
  • --directory:测试目录
  • --ioengine:测试时下发 IO 的方式;通常用 libaio 即可
  • --rw:常用的有 read,write,randread,randwrite,分别代表顺序读写和随机读写
  • --bs:每次 IO 的大小
  • --size:每个线程的 IO 总大小;通常就等于测试文件的大小
  • --numjobs:测试并发线程数;默认每个线程单独跑一个测试文件
  • --direct:在打开文件时添加 O_DIRECT 标记位,不使用系统缓冲,可以使测试结果更稳定准确

结果如下:

# Sequential
WRITE: bw=703MiB/s (737MB/s), 703MiB/s-703MiB/s (737MB/s-737MB/s), io=4096MiB (4295MB), run=5825-5825msec
READ: bw=817MiB/s (856MB/s), 817MiB/s-817MiB/s (856MB/s-856MB/s), io=4096MiB (4295MB), run=5015-5015msec

# Random
WRITE: bw=285MiB/s (298MB/s), 285MiB/s-285MiB/s (298MB/s-298MB/s), io=4096MiB (4295MB), run=14395-14395msec
READ: bw=93.6MiB/s (98.1MB/s), 93.6MiB/s-93.6MiB/s (98.1MB/s-98.1MB/s), io=4096MiB (4295MB), run=43773-43773msec

Vdbench 多机性能测试

Vdbench 也是业界常见的文件系统评测工具,且很好地支持了多机并发测试。

测试环境

与 JuiceFS Bench 测试环境类似,只是多开了两台同配置主机,一共三台。

准备工作

需要在每个节点相同路径下安装 vdbench:

  1. 官网下载 50406 版本
  2. 安装 Java:apt-get install openjdk-8-jre
  3. 测试 vdbench 安装成功:./vdbench -t

然后,假设三个节点名称分别为 node0,node1 和 node2,则需在 node0 上创建配置文件,如下(测试大量小文件读写):

$ cat jfs-test
hd=default,vdbench=/root/vdbench50406,user=root
hd=h0,system=node0
hd=h1,system=node1
hd=h2,system=node2

fsd=fsd1,anchor=/mnt/jfs/vdbench,depth=1,width=100,files=3000,size=128k,shared=yes

fwd=default,fsd=fsd1,operation=read,xfersize=128k,fileio=random,fileselect=random,threads=4
fwd=fwd1,host=h0
fwd=fwd2,host=h1
fwd=fwd3,host=h2

rd=rd1,fwd=fwd*,fwdrate=max,format=yes,elapsed=300,interval=1

参数说明:

  • vdbench=/root/vdbench50406:指定了 vdbench 工具的安装路径
  • anchor=/mnt/jfs/vdbench:指定了每个节点上运行测试任务的路径
  • depth=1,width=100,files=3000,size=128k:定义了测试任务文件树结构,即测试目录下再创建 100 个目录,每个目录内包含 3000 个 128 KiB 大小的文件,一共 30 万个文件
  • operation=read,xfersize=128k,fileio=random,fileselect=random:定义了实际的测试任务,即随机选择文件下发 128 KiB 大小的读请求

结果如下:

FILE_CREATES        Files created:                              300,000        498/sec
READ_OPENS          Files opened for read activity:             188,317        627/sec

系统整体创建 128 KiB 文件速度为每秒 498 个,读取文件速度为每秒 627 个。

总结

本文从环境配置、工具介绍、实例测试等角度全方位的分享了对 JuiceFS 进行性能评估的整体流程,准确的性能评估可以帮助优化 JuiceFS 更好的适配你的应用场景。最后,欢迎大家积极记录并分享自己的测试过程和结果到 JuiceFS 论坛或用户群。

推荐阅读:知乎 x JuiceFS:利用 JuiceFS 给 Flink 容器启动加速

如有帮助的话欢迎关注我们项目 Juicedata/JuiceFS 哟! (0ᴗ0✿)

有关JuiceFS 性能评估指南的更多相关文章

  1. Ruby 的数字方法性能 - 2

    我正在使用Ruby解决一些ProjectEuler问题,特别是这里我要讨论的问题25(Fibonacci数列中包含1000位数字的第一项的索引是多少?)。起初,我使用的是Ruby2.2.3,我将问题编码为:number=3a=1b=2whileb.to_s.length但后来我发现2.4.2版本有一个名为digits的方法,这正是我需要的。我转换为代码:whileb.digits.length当我比较这两种方法时,digits慢得多。时间./025/problem025.rb0.13s用户0.02s系统80%cpu0.190总计./025/problem025.rb2.19s用户0.0

  2. ruby - Ruby 性能中的计时器 - 2

    我正在寻找一个用ruby​​演示计时器的在线示例,并发现了下面的代码。它按预期工作,但这个简单的程序使用30Mo内存(如Windows任务管理器中所示)和太多CPU有意义吗?非常感谢deftime_blockstart_time=Time.nowThread.new{yield}Time.now-start_timeenddefrepeat_every(seconds)whiletruedotime_spent=time_block{yield}#Tohandle-vesleepinteravalsleep(seconds-time_spent)iftime_spent

  3. ruby-on-rails - 如果条件与 &&,是否有任何性能提升 - 2

    如果用户是所有者,我有一个条件来检查说删除和文章。delete_articleifuser.owner?另一种方式是user.owner?&&delete_article选择它有什么好处还是它只是一种写作风格 最佳答案 性能不太可能成为该声明的问题。第一个要好得多-它更容易阅读。您future的自己和其他将开始编写代码的人会为此感谢您。 关于ruby-on-rails-如果条件与&&,是否有任何性能提升,我们在StackOverflow上找到一个类似的问题:

  4. ruby - 在 Ruby 中的另一个上下文中评估潜在的相对 URI - 2

    我在Ruby程序中有两个URI。一个肯定是绝对URI,另一个可能是绝对URI或相对URI。我想在第一个的上下文中将第二个转换为绝对URI,所以如果第一个是http://pupeno.com/blog第二个是/about,结果应该是http://pupeno.com/about.有什么想法吗? 最佳答案 Ruby的内置URI和Addressablegem,做这个简短的工作。我更喜欢Addressable,因为它功能更全面,但URI是内置的。require'uri'URI.join('http://pupeno.com/blog','/

  5. ruby - block 内的实例评估 - 2

    我有一个Builder类,可让您添加到其中一个实例变量:classBuilderdefinitialize@lines=[]enddeflinesblock_given??yield(self):@linesenddefadd_line(text)@lines现在,我该如何改变它my_builder=Builder.newmy_builder.lines{|b|b.add_line"foo"b.add_line"bar"}pmy_builder.lines#=>["foo","bar"]进入这个?my_builder=Builder.newmy_builder.lines{add_li

  6. ruby - 使用 autoload 与 ruby​​ 中的 require 进行惰性评估? - 2

    在我的代码中,我使用自动加载进行惰性评估,这样我可以更快地加载程序并在需要时加载文件,我没有看到很多人使用它,但在Thin项目中我注意到自动加载已被广泛使用,反正只是想知道使用它是否有任何风险。 最佳答案 autoload是notthreadsafe并将在未来的Ruby版本中弃用。这是proofbyMatz(ruby的创造者)。 关于ruby-使用autoload与ruby​​中的require进行惰性评估?,我们在StackOverflow上找到一个类似的问题:

  7. Ruby 和指南针路径与 yeoman 项目 - 2

    我安装了ruby​​、yeoman,当我运行我的项目时,出现了这个错误:Warning:Running"compass:dist"(compass)taskWarning:YouneedtohaveRubyandCompassinstalledthistasktowork.Moreinfo:https://github.com/gruUse--forcetocontinue.Use--forcetocontinue.我有进入可变session目标的路径,但它不起作用。谁能帮帮我? 最佳答案 我必须运行这个:geminstallcom

  8. ruby - 如何找到我的 Ruby 应用程序中的性能瓶颈? - 2

    我编写了一个Ruby应用程序,它可以解析来自不同格式html、xml和csv文件的源中的大量数据。我如何找出代码的哪些区域花费的时间最长?有没有关于如何提高Ruby应用程序性能的好资源?或者您是否有任何始终遵循的性能编码标准?例如,你总是用加入你的字符串吗?output=String.newoutput或者你会使用output="#{part_one}#{part_two}\n" 最佳答案 好吧,有一些众所周知的做法,例如字符串连接比“#{value}”慢得多,但是为了找出您的脚本在哪里消耗了大部分时间或比所需时间更多,您需要进行分

  9. STM32的HAL和LL库区别和性能对比 - 2

    LL库和HAL库简介LL:Low-Layer,底层库HAL:HardwareAbstractionLayer,硬件抽象层库LL库和hal库对比,很精简,这实际上是一个精简的库。LL库的配置选择如下:在STM32CUBEMX中,点击菜单的“ProjectManager”–>“AdvancedSettings”,在下面的界面中选择“AdvancedSettings”,然后在每个模块后面选择使用的库总结:1、如果使用的MCU是小容量的,那么STM32CubeLL将是最佳选择;2、如果结合可移植性和优化,使用STM32CubeHAL并使用特定的优化实现替换一些调用,可保持最大的可移植性。另外HAL和L

  10. Simulink方法总结和避坑指南(一)——Simulink入门与基本调试方法 - 2

    文章目录一、项目场景二、基本模块原理与调试方法分析——信源部分:三、信号处理部分和显示部分:四、基本的通信链路搭建:四、特殊模块:interpretedMATLABfunction:五、总结和坑点提醒一、项目场景  最近一个任务是使用simulink搭建一个MIMO串扰消除的链路,并用实际收到的数据进行测试,在搭建的过程中也遇到了不少的问题(当然这比vivado里面的debug好不知道多少倍)。准备趁着这个机会,先以一个很基本的通信链路对simulink基础和相关的debug方法进行总结。  在本篇中,主要记录simulink的基本原理和基本的SISO通信传输链路(QPSK方式),计划在下篇记

随机推荐