fos*_*4me 6 memory oom crash fio
我被要求fio
为这个测试数据集提供基准测试结果:1048576x1MiB。因此,整体大小为1TiB。该集合包含2^20 个 1MiB文件。服务器运行CentOS Linux release 7.8.2003 (Core)
。它有足够的内存:
[root@tbn-6 src]# free -g
total used free shared buff/cache available
Mem: 376 8 365 0 2 365
Swap: 3 2 1
Run Code Online (Sandbox Code Playgroud)
它实际上不是物理服务器。相反,它是一个具有以下 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
[...]
Run Code Online (Sandbox Code Playgroud)
为什么是码头工人?我们正在开展一个评估使用容器而不是物理服务器的适当性的项目。回到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
Run Code Online (Sandbox Code Playgroud)
对我来说一切都很好。在撰写本文时,我还使用 GCC 9编译了最新的 fio 3.23。
[root@tbn-6 src]# fio --version
fio-3.23
Run Code Online (Sandbox Code Playgroud)
这是作业文件:
[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
Run Code Online (Sandbox Code Playgroud)
注:以上内容中,可取出以下内容:
[...]
gtod_reduce=1
[...]
runtime=180
group_reporting=1
[...]
Run Code Online (Sandbox Code Playgroud)
其余的必须保留。这是因为在我们看来,运行 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)
Run Code Online (Sandbox Code Playgroud)
好的,是时候使用 --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)
Run Code Online (Sandbox Code Playgroud)
回到原点 :(
我肯定错过了什么。非常感谢任何帮助。
(TL;DR设置--alloc-size
为大数字会有所帮助)
我打赌你可以简化这项工作并仍然重现问题(这对任何查看此内容的人都会有帮助,因为可查看的地方较少)。我猜关键在于该opendir
选项以及您所说的目录包含“2^20 1MiB 文件”这一事实......
如果您阅读文档,--alloc-size
您会注意到它提到:
如果在启用randommap的情况下运行大型作业,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-size选项)。目前尚不清楚这是否是此特定案例中的一个因素,但请参阅下面的“原始作业仅停止在 8 个池”评论。
那么为什么设置没有--alloc-size=776
帮助呢?看看你写的内容,每个池的块没有增加似乎很奇怪,对吧?我注意到第二次您的池增长到最大 16 个(https://github.com/axboe/fio/blob/fio-3.23/smalloc.c#L24 )。的文档是--alloc-size
这样说的:
--alloc-size= kb分配大小为kb 的额外内部 Smalloc 池(以KiB为单位)。[...] 池大小默认为16MiB。[强调]
您使用--alloc-size=776
... 776 KiB 不是比 16 MiB 小吗?这将使每个池小于默认值,并且可以解释为什么它在第二次运行中放弃之前尝试将池数量增加到最大值 16。
(2 ** 20 * 416) / 8 / 1024 = 53248 (but see the update below)
Run Code Online (Sandbox Code Playgroud)
上述算术表明,如果您要拥有 8 个池,总共大约 416 MB 的 RAM,那么您希望每个池的大小大约为 52 MB。使用时会发生什么--alloc-size=53248
?
更新:上面计算的数字太低。在评论中,提问者报告说需要使用更高的设置。--alloc-size=1048576
(不过,我有点担心原来的作业只停在 8 个池(128 MiB)。这是否表明尝试增长到第九个 16 MiB 池是有问题的?)
最后,fio 文档似乎暗示当您请求随机 I/O 的特定分布时,这些数据结构正在被分配。这表明,如果 I/O 是顺序的,或者 I/O 使用随机偏移但不必遵守分布,那么也许不需要分配这些数据结构...如果使用会发生什么norandommap
?
(旁白:blocksize=2M
但是你的文件有 1MiB 大 - 这是正确的吗?)
对于一个随意的服务器故障答案来说,这个问题感觉太大而且太专业,并且可能从 fio 项目本身得到更好的答案(请参阅https://github.com/axboe/fio/blob/fio-3.23/REPORTING-BUGS,https:// /github.com/axboe/fio/blob/fio-3.23/README#L58)。
祝你好运!