기본적으로 저는 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.c
cd /path/I/want/to/know/size/of; /path/of/async_size