基本上我有一个 3TB 磁盘,里面有 4 个目录,这些目录里面有数百个目录。
我想查看任何目录的相对大小,它不必非常准确,并且以 GB 为单位显示会更好。
我尝试过 du -sh /disk/dir1/asdf
但由于这些目录有数百 GB,因此上述过程需要 10 多分钟。
“ncdu”很好,但同样,需要很长时间才能完成所有内容(几个小时)。
df -h 运行良好,快速并能给出相对大小,但是它只显示磁盘,有没有办法模拟 df -h 的功能但调整深度大小?
如果有帮助的话,我们正在该磁盘上使用 glusterfs,也许有办法使用该选项来加快速度?不过,通用方法是最好的。
答案1
df -h 运行良好,快速并能给出相对大小,但是它只显示磁盘,有没有办法模拟 df -h 的功能但调整深度大小?
不,df -h
只是询问文件系统完全使用了多少空间。该信息仅存在于整个文件系统,而不存在于子目录。
如果有帮助的话,我们正在该磁盘上使用 glusterfs,也许有办法使用该选项来加快速度?不过,通用方法是最好的。
在与实际(元数据)存储连接的延迟尽可能低的计算机上进行计数。
您可能会受到获取文件列表所需时间的限制,并询问各个文件的大小。我不太了解 glusterfs 及其实现,但是:
du -s .
执行以下操作:对于每个目录,获取目录中的条目列表(使用getdents
( 64
) 系统调用,它反过来启动文件系统以提供文件列表)。然后,按顺序遍历这些条目,然后获取每个文件的文件统计信息(使用 ( new
) fstat
( at
) 系统调用,它反过来启动文件系统以提供有关每个文件的信息),其中包含文件大小,用于计算总数。
对于遇到的每个目录,它都会向下递归。
因此,如果您有以下目录树,则存在大量通信:
.
├── b
│ ├── b
│ ├── c
│ │ ├── e
│ │ ├── g
│ │ └── h
│ ├── d
│ └── f
├── bar
├── baz
├── foo
└── foooo
在找到 的./baz
信息之前,不会获取 的尺寸信息。./bar
因为获取该信息的大部分时间都花在等待文件系统从 glusterfs 守护进程获取信息(通过网络!),所以程序主要做的是等待很长时间,然后请求下一个文件信息,然后再次等待,依此类推。您的计算机将花费很少的时间来做某事(例如了解服务器发送给您的内容或添加大小),并且花费大量时间等待。
如果 glusterfs 能够异步请求(我们可以非常确定它是),一个简单的解决方案是将“获取目录列表”和“获取文件大小”方面放入单独的功能单元中,并获取文件大小多线程(在简单和极端的情况下,为每个文件生成一个线程)。
你可以使用奥莱·丹格的parallel
.
首先,用于find /disk/dir1/asdf -type f
(顺序)获取所有文件的列表。 (这也可以是多线程的,但这会更复杂,而且还取决于该目录下的“宽”与“深”目录结构的程度);然后,使用parallel
并行的方式在每个文件上运行stat -f '%s'
,最后合并结果并将其相加。
然后,虽然您没有减少等待的总时间,但许多等待是并行发生的。
这在 C++ 中也可能是一件好事,因为这std::async
使得收集数据的任务变得相当简单。就像是:
#include <cstdint>
#include <filesystem>
#include <future>
#include <iostream>
#include <vector>
namespace fs = std::filesystem;
using future_t = std::future<std::uintmax_t>;
int main() {
std::vector<future_t> futures;
for(auto const& dir_entry : fs::recursive_directory_iterator(".")) {
if(fs::is_regular_file(dir_entry)) {
futures.emplace_back(std::async(
std::launch::async,
[](auto path) {
return fs::file_size(path);
},
dir_entry
));
}
}
std::uintmax_t total_size = 0;
for(auto& future : futures) {
total_size += future.get();
}
std::cout << "Total size " << total_size << "b\n";
}
(尝试编译器资源管理器!或者复制到文件main.c
,并使用本地构建g++ -O3 -std=c++17 -lpthread -o async_size main.c
;运行通过cd /path/I/want/to/know/size/of; /path/of/async_size
)