因为某些需求,经常要在 linux 环境下读写/删除创建 千万量级的文件,每个文件大小在 1M 左右。
文件系统是 GPFS parallel file system ,顺序 IO 估计有个 100GB/s 吧。创建的时候问题不大,用 mpi 速度还挺快,几乎无感。2000 个 mpi 任务几分钟就写好了,所以感觉 IO 应该不是瓶颈(?)
只不过删除的时候有点痛苦,不太想调用运算集群来删,有点浪费资源,希望能用一个 node 来快速完成删除,最好调用小于 128 个核心。
rm 太慢,就不考虑了。试过 rscyn ,性能也一般。现在用 find + parellel rm ,用 10 个进程删,凑合能用。不知道各位有没有什么好的建议快速删除这些文件。
另外偶尔也有备份的需求,因为不太常用,基本就用 tar 打包,丢在那半天一天也就打包好了,打包完 1~10t 左右的量级。如果哪位大佬有快速打包/解包的方案建议在此一并谢过。

补充一下,没有 root 权限。所以很多命令用不了。

感谢大家的回复。看了一下,感觉最靠谱的还是用 多线程 调用 rm/rsync 删 比较靠谱。实在不行就调用一个 128 核心的运算 node 来删除吧。有没有什么关于打包的建议。不需要压缩,硬盘容量足够。就是想 快速 把千万个小文件集合成一个大文件,甚至可以接受容量 10 倍左右的损失(增长)。主要就是要快,打包解包都快最好。我这个文件系统文件数有配额限制,不能超过 2 亿,但是体积几乎没有。

抛砖引玉mkdir /tmp/arsync -av --delete /tmp/a/ /dir-you-need-del/

rimraf 不知道基于啥实现,node_modules 都能干,window/linux 都可以

容器或者虚拟磁盘?

mkfs

或许可以换个思路。挂载磁盘镜像,写文件写到镜像里,删除只需要删除镜像文件即可。另外 qcow2 可以开启压缩,直接当作是打包

我觉得可能是这个文件系统读取文件夹下文件的性能比较差,时间都花在 find 命令上了。试试创建的时候手动 redis,sqlite 之类的方法把文件信息记下来,然后删除时,用完整路径直接去删

的确 删除文件一直是个老大难问题一般来说单线程 rsync 是最快的你后台 io 够的话,试试多线程 rsync ,find 限制深度 然后用 xargs/parallel 去删

换个思路,不在乎时间段话,ionice 慢慢删?

单独分块盘来写,写完就直接格式化

经常删除 npm 一大堆上万个小文件,发现 ssd 的在线 trim 和定时 trim 性能差别太大了,至少速度差有好几倍以上。似乎现在的 linux 也都推荐定时 trim 了。 wiki.archlinux.org/title/Solid_state_drive

我现在就是 find 限制深度然后 xargs/parallel 删,感觉还是性能不满意,不说 10 分钟删完,至少写入时间的 2~3 倍内删完吧。我写入大概只要 10 分钟。 可惜没权限挂载硬盘。 我也考虑过建个文件表。这样性能会比 find 直接删文件夹好么?这样可以考虑用 mpi 来删倒是。

我也推荐#1 的方法

需要都保留吗?不需要的话根据时间间隔删。需要全部放一起吗?不需要的话分 N 个文件夹慢慢删tar 不能做压缩

确实路过问一下,为什么 linux 删除一个目录只能一个个删掉目录下文件,而不是直接把目录对应的 node 直接删了,这样所有文件不就失去索引相当于被删了吗如果我不在乎数据安全之类的只追求快速删目录,有办法直接把目录的 node 干掉吗?

你这个需求可能有问题如果有删除掉需求,那么创建的时候就应该面向删除做优化

最直接的一点,删目录得把其子文件所占用的空间全部释放掉,这里其实有个容易混淆的点就在于,这个目录下面假设有两个 1g 的.txt 文件,那么从上层视角来看,这个目录占了 2g ,但真实情况是,这个目录本身可能只占用了 2 个块( inode 占一个块,dentry table 占一个块),也就是 8KB 而已。因此,如果你不去遍历下面的子文件,而是只拿掉这个目录本身,那意味着最多只能回收 8KB ,而下面的那两个 1g 的 txt 所占用的块你怎么回收?

//创建并挂载虚拟磁盘fallocate -l 10G t.img && mkfs.ext4 t.img && mkdir /tmp/TestMountPoint && mount -o loop t.img /tmp/TestMountPoint//用完删除umount /tmp/TestMountPoint && rm -f t.img

感觉目前应该没啥更优的解法了,普通的文件系统可能要删更久,大部分文件系统都没有对删除一堆小文件做特殊优化,每个删除都是个复杂的原子操作。除非你可以不走 linux 的文件系统,直接调用某些 gpfs 的某些接口。

btrfs subvolume 可以当目录用,删就是整个删,一次操作完成。因为 vfs 需要支持各种文件系统的实现,一个远程挂载的共享你怎么“直接把目录对应的 node 干掉”?

rsync 在 ext4 这样的文件系统上快,在 GPFS 上真不一定能跑过 parallel

如果需要频繁的创建、删除,是不是可以直接修改,别再删了😄️

可以试试 find + -delete ,我感觉挺快的find . -type f -name "{file_pattern}" -delete

并行删除不一定比顺序删除快,因为瓶颈在文件 I/O 操作。"The I/O bound is the limiting factor (CPU, disk and memory utilisation was very low) and parallelisation just adds some overhead (in the simple case)."

附议我的实践经验也是 find 的 -delete 参数比 xargs 并行删除要快得多

歪个楼,Linux 不知道,但我在 Win 下这么搞:Get-ChildItem -Recurse "PATH" | Remove-Item -Force -Recurse比单纯 Remove-Item -Force -Recurse "PATH" 快很多

fsck 回收。哈哈哈哈

rm -rf node_modules 想不到更快的了,这个比 win 删除可快多了即便是在 win 下,用 git bash rm 也比 win 点删方便快速

不要删 移送到回收站 定期清理回收站

楼上有提到过,find 有个 -delete 参数,可以试一下

我记得看过一个测试,大多数情况下都是 rm 最快,比 rsync find 之类快多了,毕竟专门干这个的。上面说的 qcow2 是个好方案,不一定非要 root 权限,可以丢到虚拟机里操作

有没有可能一个程序把很多文件内容清空,另一个进程来删文件?

有个思路,直接改文件系统的索引

www.yuque.com/wangsendi/linux/ryil60rq7kouuto7有写过笔记

是的,我知道 tar 不能压缩,我只是为了把小文件打包而已,硬盘容量足够大,1~2PB 呢。 可惜运行的是一个比较大且老旧的程序,比较难改了。而且为了删文件去改好像也不值当。 赞同。我去查查 gpfs 的手册吧。 创建新的比修改旧的快的多的多,而且也节省计算资源,没理由去修改啊。 我这里 IO 应该不是瓶颈,并行删除肯定是更快的。就是想问问有没有什么更高效的删除操作。 rm 单线程删除的确还行,可惜本身不支持多线程,我现在其实就是多开 rm 。

我问了一下 GPT-4o,感觉答案挺靠谱的。

删除卡在元数据操作,线程高了估计也没太大帮助。如果能改代码,把文件操作变为操作一个大文件不同 offset ,最后把大文件删除即可。

那你用 unlink 嘛,多少能快点

offset ?是不是可以 loopback ?