find는 깊이 우선 검색을 수행하는 방식이므로 항상 사전순으로 파일을 나열합니다. 이러한 제한을 완화할 의향이 있다면 찾기 병렬성을 높이거나 다른 유사한 도구를 사용하여 빈 파일을 찾을 수 있습니까? (다른 유사한 기준을 사용하여 파일을 찾는 전략도 궁금합니다만 find
, 구체성을 위해 빈 파일을 사용하겠습니다).
그래서 나는 내 홈 디렉토리에 있는 모든 빈 파일을 어떤 순서로든 찾으려고 노력하고 있습니다.
OS X에서 bash를 사용하여 다음 명령을 실행합니다.
$ find . -type f -empty >& /dev/null
real 0m10.334s
user 0m0.525s
sys 0m5.568s
병렬성을 향상시키기 위해 제가 생각할 수 있는 가장 간단한 방법을 사용하고 Perl 스크립트를 사용하여 디렉터리별 조회를 호출했습니다. Perl 스크립트는 find
자체 프로세스의 각 최상위 디렉터리나 파일에서만 실행됩니다.
이 스크립트의 총 실행 시간은 단일 조회의 절반보다 약간 짧습니다.
#!/usr/bin/env perl
use strict;
use warnings;
opendir(my $fh, '.');
while (readdir($fh)) {
my $item = $_;
next if $item eq '.';
next if $item eq '..';
my $cpid = fork();
if ($cpid == -1) {
die;
} elsif ($cpid == 0) {
exec 'find', "./$item", '-type', 'f', '-empty', or die;
}
}
while (wait() != -1) {}
예를 들어
$ time perl find-parallel.pl >& /dev/null
real 0m4.245s
user 0m1.126s
sys 0m8.281s
find
일종의 스크립트를 사용하여 어느 정도 깊이에서 독립 실행형을 수동으로 실행하는 것은 이 문제를 해결하는 다소 서투른 방법처럼 보입니다. 더 좋은 방법이 있나요?
답변1
먼저 작은 문제가 있습니다. 적어도 Linux에서는 find의 출력 순서가 알파벳순이 아닙니다. 대신 디렉터리 인덱스 순서(일반적으로 생성 순서)입니다.
exec
그 자체( syscall 까지 execve
)는 작업 중인 규모에서 상당한 오버헤드를 가지므로 이를 피하는 것이 좋습니다.
솔루션의 일반적인 프레임워크로서 최소한 2개의 스레드 기반이 필요합니다.
- 큐 관리자
- 노동자)
논리:
- 대기열은 단일 디렉터리로 시작됩니다
.
. - 대기열에서 무언가를 사용할 수 있고 아직 병렬 스레드의 한계에 도달하지 않은 경우 대기열의 항목으로 작업자 스레드를 시작하십시오.
- 작업자: 지정된 디렉터리를 비재귀적으로 읽습니다.
- 확인된 새 디렉터리의 경우 해당 디렉터리를 대기열에 추가합니다.
- 다른 새 파일은 정상적으로 처리됩니다.
특별한 상황을 처리해야 합니다.
- 동일한 항목을 가리키는 여러 개의 기호 링크입니다.
- 다른 디렉토리에 대한 기호 링크(디자인 요구 사항에 따라 이를 따르지 않거나 여러 번 따라야 할 수도 있음).
- 더 높은 수준에 대한 기호 링크를 따르는 경우 반복됩니다.
이것이 비병렬 조회보다 성능이 더 좋습니까? 이것은 어려운 질문이며 사용되는 파일 시스템/커널에 따라 다릅니다.
예를 들어 사전 구축된 솔루션을 찾고 있다면 Go Parallel Directory Walker를 찾으세요. 단, 다음 비용에 유의하세요.추가 stat
통화.
답변2
이것은 제가 C++로 작성한 Github의 무료 Linux 병렬 검색 도구입니다. https://github.com/breuner/elfindo
다음과 같이 사용하여 빈 파일을 찾을 수 있습니다.
$ elfindo . -type f -size 0
매개변수를 통해 명시적으로 스레드 수를 설정할 수 있습니다 -threads
.
$ elfindo . -type f -size 0 -threads 32