대형 테라바이트 디렉터리에서 디렉터리 크기를 빠르게 검색하는 방법

대형 테라바이트 디렉터리에서 디렉터리 크기를 빠르게 검색하는 방법

기본적으로 저는 4개의 디렉토리가 있는 3TB 디스크를 가지고 있으며 그 안에는 수백 개의 디렉토리가 있습니다.

모든 디렉토리의 상대적인 크기를 보고 싶습니다. 정확할 필요는 없으며 GB 단위로 표시하는 것이 더 좋습니다.

du -sh /disk/dir1/asdf를 시도했습니다.

그러나 이러한 디렉터리는 수백 기가바이트에 달하기 때문에 위의 프로세스는 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'하고 마지막으로 결합합니다. 결과를 확인하고 추가하세요.

그러면 전체 대기 시간을 줄이지는 못하더라도 많은 대기가 병렬로 발생하게 됩니다.

std::async이는 데이터 수집 작업을 매우 간단하게 만들어주기 때문에 C++에서도 좋은 점일 수 있습니다 . 그것은 다음과 같습니다:

#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.ccd /path/I/want/to/know/size/of; /path/of/async_size

관련 정보