我被要求fio
针对此测试数据集提供基准测试结果:1048576x1MiB。因此,整体规模是1TiB. 该套装包含2^20 1MiB文件。服务器运行CentOS Linux release 7.8.2003 (Core)
。它具有足够的 RAM:
[root@tbn-6 src]# free -g
total used free shared buff/cache available
Mem: 376 8 365 0 2 365
Swap: 3 2 1
它实际上并不是物理服务器。相反,它是一个具有以下 CPU 的 Docker 容器:
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 48
On-line CPU(s) list: 0-47
Thread(s) per core: 2
Core(s) per socket: 12
Socket(s): 2
NUMA node(s): 2
Vendor ID: GenuineIntel
CPU family: 6
Model: 85
Model name: Intel(R) Xeon(R) Gold 6146 CPU @ 3.20GHz
[...]
为什么选择docker?我们正在做一个项目,评估使用容器代替物理服务器的可行性。回到问题上fio
。
我记得以前处理包含许多小文件的数据集时遇到过麻烦fio
。因此,我做了以下检查:
[root@tbn-6 src]# ulimit -Hn
8388608
[root@tbn-6 src]# ulimit -Sn
8388608
[root@tbn-6 src]# cat /proc/sys/kernel/shmmax
18446744073692774399
在我看来一切都很好。截至撰写本文时,我还进行了编译。最新的 fio 3.23使用 GCC 9。
[root@tbn-6 src]# fio --version
fio-3.23
这是作业文件:
[root@tbn-6 src]# cat testfio.ini
[writetest]
thread=1
blocksize=2m
rw=randwrite
direct=1
buffered=0
ioengine=psync
gtod_reduce=1
numjobs=12
iodepth=1
runtime=180
group_reporting=1
percentage_random=90
opendir=./1048576x1MiB
注意:从上式中,可以删除以下内容:
[...]
gtod_reduce=1
[...]
runtime=180
group_reporting=1
[...]
其余的部分必须被保留。这是因为在我们看来,运行 fio 时,作业文件的设置方式应尽可能接近地模拟应用程序与存储的交互,即使知道fio
!= the application
。
我第一次跑步是这样的
[root@tbn-6 src]# fio testfio.ini
smalloc: OOM. Consider using --alloc-size to increase the shared memory available.
smalloc: size = 368, alloc_size = 388, blocks = 13
smalloc: pool 0, free/total blocks 1/524320
smalloc: pool 1, free/total blocks 8/524320
smalloc: pool 2, free/total blocks 10/524320
smalloc: pool 3, free/total blocks 10/524320
smalloc: pool 4, free/total blocks 10/524320
smalloc: pool 5, free/total blocks 10/524320
smalloc: pool 6, free/total blocks 10/524320
smalloc: pool 7, free/total blocks 10/524320
fio: filesetup.c:1613: alloc_new_file: Assertion `0' failed.
Aborted (core dumped)
好的,现在是时候使用--alloc-size
[root@tbn-6 src]# fio --alloc-size=776 testfio.ini
smalloc: OOM. Consider using --alloc-size to increase the shared memory available.
smalloc: size = 368, alloc_size = 388, blocks = 13
smalloc: pool 0, free/total blocks 1/524320
smalloc: pool 1, free/total blocks 8/524320
smalloc: pool 2, free/total blocks 10/524320
smalloc: pool 3, free/total blocks 10/524320
smalloc: pool 4, free/total blocks 10/524320
smalloc: pool 5, free/total blocks 10/524320
smalloc: pool 6, free/total blocks 10/524320
smalloc: pool 7, free/total blocks 10/524320
smalloc: pool 8, free/total blocks 8/524288
smalloc: pool 9, free/total blocks 8/524288
smalloc: pool 10, free/total blocks 8/524288
smalloc: pool 11, free/total blocks 8/524288
smalloc: pool 12, free/total blocks 8/524288
smalloc: pool 13, free/total blocks 8/524288
smalloc: pool 14, free/total blocks 8/524288
smalloc: pool 15, free/total blocks 8/524288
fio: filesetup.c:1613: alloc_new_file: Assertion `0' failed.
Aborted (core dumped)
回到原点 :(
我肯定遗漏了什么。如能得到任何帮助我将不胜感激。
答案1
(总结设置--alloc-size
较大的数字有帮助)
我敢打赌,你可以简化这项工作,但仍然可以重现问题(这对任何看这个问题的人来说都是有帮助的,因为要看的地方更少了)。我猜关键在于opendir
选项和您所说的目录包含“2^20 1MiB 文件”的事实......
如果你读过--alloc-size
你会注意到它提到:
如果运行大型作业随机地图启用后,fio 可能会耗尽内存。
默认情况下,fio 会将随机 I/O 均匀地分布在文件中(每个块每次写入一次),但要做到这一点,它需要跟踪已写入的区域,这意味着它必须为每个文件保留一个数据结构。好的,您可以看到这是怎么回事...
为某些数据结构预留的内存池(因为它们必须在作业之间共享)。最初有 8 个池(https://github.com/axboe/fio/blob/fio-3.23/smalloc.c#L22),默认情况下每个池的大小为 16 MB(https://github.com/axboe/fio/blob/fio-3.23/smalloc.c#L21)。
每个执行随机 I/O 的文件都需要一个与之配合的数据结构。根据您的输出,我们猜测每个文件都会强制分配一个 368 字节 + 标头的数据结构(https://github.com/axboe/fio/blob/fio-3.23/smalloc.c#L434),总计 388 字节。因为池在 32 字节的分配下工作(https://github.com/axboe/fio/blob/fio-3.23/smalloc.c#L70)这意味着我们实际上从每个文件的池中取出 13 个块(416 字节)。
出于好奇,我有以下问题:
- 您是在容器中运行它吗?
- 你的最大尺寸是多少
/tmp
?
我认为上述内容与您的问题无关,但可以很好地排除。
更新:默认情况下,docker 会限制 IPC 共享内存的数量(另见其--shm 大小选项)。目前尚不清楚这是否是此特定案例的一个因素,但请参阅下面的“原始作业仅在 8 个池处停止”评论。
那么为什么设置没有--alloc-size=776
帮助?看看你写的内容,每个池的块没有增加似乎很奇怪,对吧?我注意到你的池已增长到最大值 16 (https://github.com/axboe/fio/blob/fio-3.23/smalloc.c#L24) 第二次。 的文档--alloc-size
说明了这一点:
--分配大小=千字节 分配额外的内部 smalloc 池大小千字节在基布. [...] 池大小默认为16MB.[强调]
您使用了--alloc-size=776
... 776 KiB 不是小于 16 MiB 吗?这会使每个池都小于默认值,这也许可以解释为什么在第二次运行中它试图将池的数量增加到最大值 16,然后才放弃。
(2 ** 20 * 416) / 8 / 1024 = 53248 (but see the update below)
上述算法表明,如果您要创建 8 个池,总 RAM 约为 416 MB,则每个池的大小约为 52 MB。使用时会发生什么情况--alloc-size=53248
?
更新:上面计算的数字太低了。在评论中,提问者报告称,使用更高的设置--alloc-size=1048576
是必需的。
(不过,我有点担心原始工作只停止在 8 个池(128 MiB)处。这难道不表明尝试增长到第九个 16 MiB 池是有问题的吗?)
最后,fio 文档似乎暗示,当您要求特定的随机 I/O 分布时,这些数据结构将被分配。这表明,如果 I/O 是连续的,或者 I/O 使用随机偏移量但不必遵循分布,那么这些数据结构可能不必分配……如果您使用norandommap
?
(另外:blocksize=2M
但是您的文件有 1MiB 大 - 对吗?)
这个问题对于一个随意的 serverfault 回答来说太大太专业了,fio 项目本身可能会给出更好的答案(参见https://github.com/axboe/fio/blob/fio-3.23/REPORTING-BUGS,https://github.com/axboe/fio/blob/fio-3.23/README#L58)。
祝你好运!