encontra arquivos vazios em paralelo

1

o find sempre lista arquivos em ordem lexicográfica, porque é assim que ele realiza buscas em profundidade. Se estamos dispostos a relaxar essa restrição, é possível melhorar o paralelismo de encontrar ou usar outra ferramenta semelhante para procurar arquivos vazios? (Eu também estou curioso sobre estratégias para procurar por arquivos usando outros critérios iguais a find , mas por questão de concretude vamos usar arquivos vazios).

Então, estou tentando encontrar todos os arquivos vazios no meu diretório pessoal em qualquer ordem.

No OS X usando o bash, eu corro o seguinte comando

$ find . -type f -empty >& /dev/null
real    0m10.334s
user    0m0.525s
sys 0m5.568s

Em uma tentativa de melhorar o paralelismo, eu fiz a coisa mais simples que eu poderia imaginar e usei invok find uma vez por diretório usando um script Perl. O script Perl apenas executa find por diretório ou arquivo de nível superior em seu próprio processo.

O tempo total decorrido para o script é um pouco menos da metade do que o único encontrado.

#!/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) {}

Por exemplo

$ time perl find-parallel.pl >& /dev/null
real    0m4.245s
user    0m1.126s
sys 0m8.281s

Usar um script de algum tipo para executar manualmente find s em uma determinada profundidade parece ser uma abordagem bastante desajeitada para esse problema. Existe uma maneira melhor?

    
por Gregory Nisbet 23.01.2017 / 07:58

1 resposta

2

Minor nit first: A ordem de saída para find não é lexográfica, pelo menos no Linux. Em vez disso, está na ordem do índice do diretório (que é freqüentemente a ordem de criação).

exec em si, até o syscall execve , tem uma sobrecarga não trivial na escala em que você está trabalhando, então é preciso evitá-lo.

Como estrutura geral para a solução, você precisa de pelo menos uma base de dois tópicos:

  • gerenciador de filas
  • trabalhador (es)

Lógica:

  1. A fila começa com um único diretório . .
  2. Sempre que houver algo disponível na fila e não tivermos atingido o limite de encadeamentos paralelos, inicie um trabalhador com um item da fila.
  3. O trabalhador: lê o diretório fornecido, não recursivamente.
  4. Para o novo diretório que ele vê, anexe o diretório à fila.
  5. Para outro novo arquivo, manipule normalmente.

Casos especiais que precisam ser tratados:

  • Múltiplos links simbólicos para a mesma coisa.
  • Links simbólicos para outros diretórios (dependendo das suas necessidades de design, você pode não seguir ou ter que seguir várias vezes).
  • Loops circulares se seguirem links simbólicos para níveis superiores.

Isso funcionará melhor do que um resultado não paralelo? Essa é uma pergunta difícil e também se resume ao sistema de arquivos / kernel em uso.

Se você está procurando soluções pré-construídas, por exemplo, procure por walkers de diretórios paralelos, mas cuidado com o custo de extra stat chamadas .

    
por 31.12.2017 / 01:03

Tags