我正在运行 Ubuntu 24.04,使用 ZFS 作为文件系统。这是在一台笔记本电脑上,其唯一的存储设备是 WD Black SN850X NVMe 卡。默认的 Ubuntu 安装过程配置了两个 ZFS 池:
capacity operations bandwidth
pool alloc free read write read write
-------------------------------------- ----- ----- ----- ----- ----- -----
bpool 187M 1.69G 0 0 381 204
86349523-abd9-7a45-ab84-60d7622c240f 187M 1.69G 0 0 381 204
-------------------------------------- ----- ----- ----- ----- ----- -----
rpool 286G 634G 13 31 1.11M 796K
cc31ec4d-1dd2-ed4f-9f90-fa99ec5aa3a2 286G 634G 13 31 1.11M 796K
-------------------------------------- ----- ----- ----- ----- ----- -----
/tmp
是根挂载的一部分,位于 rpool 中。
由于某些代码中的错误,我的/tmp
文件夹中一度有超过 200 万个文件。当文件夹中有这么多文件时,性能就会急剧下降——即使只是列出文件(不排序)也会暂停一秒钟以上。我删除了大部分文件,现在情况已经恢复到可控水平。但是,对文件列表的操作/tmp
仍然很慢。
当我ls --sort=none
对例如/bin
有 2,842 个条目进行计时时,我得到了如下结果:
real 0m0.088s
user 0m0.001s
sys 0m0.075s
但在 上运行同样的命令/tmp
,它目前有 4,444 个条目:
real 0m0.472s
user 0m0.007s
sys 0m0.446s
看来,短暂地存放 200 万个文件对 的结构产生了永久性的影响/tmp
?有办法解决这个问题吗?我只需要创建一个新的/tmp
并切换到它吗?
当目录中的文件超过数百万时,性能会差很多。使用哪种文件系统或块设备中有多少 IOPS 并不重要。POSIX 语义意味着维护目录中的文件概念需要大量开销。这随后成为理解文件系统内部原理的练习。
从火焰图来看,大多数堆栈源自 readdir 调用,这并不奇怪。令我惊讶的是,实际上花费时间的顶层主要是 LZ4 解压缩。这是一种快速算法。执行此操作需要数百毫秒的 CPU 时间,这意味着需要处理大量元数据,或调用大量 getdents64,或者其他一些运行缓慢的事情。
据我对ZFS 磁盘格式的了解,数据集有自己的对象集。所以是的,您可以从根池中创建一个新的 tmp 数据集并将其挂载到现有的 /tmp 上。不需要复制数据,因为它是临时文件。
或者在 /tmp 上使用 tmpfs。通过删除 ZFS 和块设备来简化操作。
为时已晚,无法防止文件过多的问题,但 OpenZFS 确实有对象配额。groupquota @group可设置并
zfs userspace
列出。也可以按用户或项目进行设置。我现在有答案了。所以,是的,这是一个已知问题。在 ZFS 的内部术语中,“如果删除 ZAP 记录导致 ZAP 对象的整个叶块被清空,则不会回收该块。”但是,这不仅是一个已知问题,而且是一个已修复的问题。:-) 该修复程序尚未在任何发行版本中提供,但预计很快就会提供。
这是修复:
https://github.com/openzfs/zfs/pull/15888