如何快速扫描大 TB 目录中的目录大小

如何快速扫描大 TB 目录中的目录大小

基本上我有一个 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)

相关内容