因为某些需求,经常要在 linux 环境下读写/删除创建 千万量级的文件,每个文件大小在 1M 左右。
文件系统是 GPFS parallel file system ,顺序 IO 估计有个 100GB/s 吧。创建的时候问题不大,用 mpi 速度还挺快,几乎无感。2000 个 mpi 任务几分钟就写好了,所以感觉 IO 应该不是瓶颈(?)
只不过删除的时候有点痛苦,不太想调用运算集群来删,有点浪费资源,希望能用一个 node 来快速完成删除,最好调用小于 128 个核心。
rm 太慢,就不考虑了。试过 rscyn ,性能也一般。现在用 find + parellel rm ,用 10 个进程删,凑合能用。不知道各位有没有什么好的建议快速删除这些文件。
另外偶尔也有备份的需求,因为不太常用,基本就用 tar 打包,丢在那半天一天也就打包好了,打包完 1~10t 左右的量级。如果哪位大佬有快速打包/解包的方案建议在此一并谢过。
1 syncake 2024-05-21 04:05:51 +08:00 抛砖引玉 mkdir /tmp/a rsync -av --delete /tmp/a/ /dir-you-need-del/ |
![]() | 2 zeusho871 2024-05-21 04:53:17 +08:00 via Android rimraf 不知道基于啥实现,node_modules 都能干,window/linux 都可以 |
3 RobinHuuu 2024-05-21 07:34:25 +08:00 via Android 容器或者虚拟磁盘? |
4 iceheart 2024-05-21 07:50:07 +08:00 via Android mkfs |
5 ho121 2024-05-21 08:01:57 +08:00 via Android 或许可以换个思路。挂载磁盘镜像,写文件写到镜像里,删除只需要删除镜像文件即可。 另外 qcow2 可以开启压缩,直接当作是打包 |
![]() | 6 lrh3321 2024-05-21 08:11:58 +08:00 via Android 我觉得可能是这个文件系统读取文件夹下文件的性能比较差,时间都花在 find 命令上了。试试创建的时候手动 redis,sqlite 之类的方法把文件信息记下来,然后删除时,用完整路径直接去删 |
7 mayli 2024-05-21 08:53:24 +08:00 的确 删除文件一直是个老大难问题 一般来说单线程 rsync 是最快的 你后台 io 够的话,试试多线程 rsync ,find 限制深度 然后用 xargs/parallel 去删 |
8 ruidoBlanco 2024-05-21 08:54:57 +08:00 换个思路,不在乎时间段话,ionice 慢慢删? |
![]() | 9 cnleon 2024-05-21 09:11:47 +08:00 单独分块盘来写,写完就直接格式化 |
![]() | 10 june4 2024-05-21 09:34:37 +08:00 经常删除 npm 一大堆上万个小文件,发现 ssd 的在线 trim 和定时 trim 性能差别太大了,至少速度差有好几倍以上。 似乎现在的 linux 也都推荐定时 trim 了。 https://wiki.archlinux.org/title/Solid_state_drive |
![]() | 11 juniorzhou OP |
![]() | 12 wenxueywx 2024-05-21 11:19:18 +08:00 我也推荐#1 的方法 |
13 a7851578 2024-05-21 11:35:34 +08:00 需要都保留吗?不需要的话根据时间间隔删。 需要全部放一起吗?不需要的话分 N 个文件夹慢慢删 tar 不能做压缩 |
![]() | 14 BeautifulSoap 2024-05-21 11:47:44 +08:00 确实路过问一下,为什么 linux 删除一个目录只能一个个删掉目录下文件,而不是直接把目录对应的 node 直接删了,这样所有文件不就失去索引相当于被删了吗 如果我不在乎数据安全之类的只追求快速删目录,有办法直接把目录的 node 干掉吗? |
15 julyclyde 2024-05-21 13:20:41 +08:00 你这个需求可能有问题 如果有删除掉需求,那么创建的时候就应该面向删除做优化 |
16 ll26571 2024-05-21 14:08:08 +08:00 @BeautifulSoap 最直接的一点,删目录得把其子文件所占用的空间全部释放掉,这里其实有个容易混淆的点就在于,这个目录下面假设有两个 1g 的.txt 文件,那么从上层视角来看,这个目录占了 2g ,但真实情况是,这个目录本身可能只占用了 2 个块( inode 占一个块,dentry table 占一个块),也就是 8KB 而已。因此,如果你不去遍历下面的子文件,而是只拿掉这个目录本身,那意味着最多只能回收 8KB ,而下面的那两个 1g 的 txt 所占用的块你怎么回收? |
![]() | 17 yang0327519 2024-05-21 14:12:40 +08:00 //创建并挂载虚拟磁盘 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 |
18 mayli 2024-05-21 14:14:11 +08:00 @juniorzhou 感觉目前应该没啥更优的解法了,普通的文件系统可能要删更久,大部分文件系统都没有对删除一堆小文件做特殊优化,每个删除都是个复杂的原子操作。除非你可以不走 linux 的文件系统,直接调用某些 gpfs 的某些接口。 |
19 Jirajine 2024-05-21 14:18:47 +08:00 @BeautifulSoap btrfs subvolume 可以当目录用,删就是整个删,一次操作完成。因为 vfs 需要支持各种文件系统的实现,一个远程挂载的共享你怎么“直接把目录对应的 node 干掉”? |
21 tianice 2024-05-21 15:24:32 +08:00 如果需要频繁的创建、删除,是不是可以直接修改,别再删了 |
![]() | 22 lucasj 2024-05-21 16:14:14 +08:00 可以试试 find + -delete ,我感觉挺快的 find . -type f -name "{file_pattern}" -delete |
![]() | 23 lucasj 2024-05-21 16:21:17 +08:00 并行删除不一定比顺序删除快,因为瓶颈在文件 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)." |
![]() | 25 LJason 2024-05-21 16:52:12 +08:00 歪个楼,Linux 不知道,但我在 Win 下这么搞: Get-ChildItem -Recurse "PATH" | Remove-Item -Force -Recurse 比单纯 Remove-Item -Force -Recurse "PATH" 快很多 |
![]() | 27 zsj1029 2024-05-21 18:56:09 +08:00 rm -rf node_modules 想不到更快的了,这个比 win 删除可快多了 即便是在 win 下,用 git bash rm 也比 win 点删方便快速 |
28 lolizeppelin 2024-05-21 19:20:29 +08:00 via iPhone 不要删 移送到回收站 定期清理回收站 |
![]() | 29 ETiV 2024-05-21 19:34:54 +08:00 楼上有提到过,find 有个 -delete 参数,可以试一下 |
30 leetom 2024-05-21 20:27:09 +08:00 我记得看过一个测试,大多数情况下都是 rm 最快,比 rsync find 之类快多了,毕竟专门干这个的。 上面说的 qcow2 是个好方案,不一定非要 root 权限,可以丢到虚拟机里操作 |
![]() | 31 jpuyy 2024-05-21 23:43:26 +08:00 有没有可能一个程序把很多文件内容清空,另一个进程来删文件? |
32 sunqb 2024-05-21 23:49:11 +08:00 via Android 有个思路,直接改文件系统的索引 |
![]() | 33 VK2CnSG6oL4S9749 2024-05-22 03:44:11 +08:00 |
![]() | 34 juniorzhou OP |
![]() | 35 Hf1G1sGBYS8QSLN8 2024-05-22 08:51:20 +08:00 我问了一下 GPT-4o,感觉答案挺靠谱的。 |
36 P0P 2024-05-22 09:41:18 +08:00 删除卡在元数据操作,线程高了估计也没太大帮助。 如果能改代码,把文件操作变为操作一个大文件不同 offset ,最后把大文件删除即可。 |
37 MrKrabs 2024-05-22 10:15:01 +08:00 那你用 unlink 嘛,多少能快点 |
![]() | 39 realpg PRO 自己搞个 file system 是最省事的办法 |