Eu tenho uma pasta que tem mais de 250 arquivos de 2 GB cada. Preciso procurar uma string / padrão nesses arquivos e gerar o resultado em um output
arquivo. Eu sei que posso executar o seguinte comando, mas é muito lento!
grep mypattern * > output
Eu quero acelerar isso. Sendo um programador em Java, sei que o multi-threading pode ser usado para acelerar o processo. Estou preso em como iniciar grep
no "modo multiencadeado" e gravar a saída em um único output
arquivo.
grep
parallelism
Abhishek
fonte
fonte
Respostas:
Existem duas soluções fáceis para isso. Basicamente, usando
xargs
ouparallel
.Abordagem xargs:
Você pode usar
xargs
comfind
o seguinte:Onde você substituirá
number_of_processes
pelo número máximo de processos que deseja iniciar. No entanto, isso não garante que você tenha um desempenho significativo caso seu desempenho seja limitado de E / S. Nesse caso, você pode tentar iniciar mais processos para compensar o tempo perdido na espera de E / S.Além disso, com a inclusão de find, você pode especificar opções mais avançadas em vez de apenas padrões de arquivo, como tempo de modificação, etc ...
Um possível problema com essa abordagem, conforme explicado pelos comentários de Stéphane, se houver poucos arquivos,
xargs
pode não iniciar muitos processos para eles. Uma solução será usar a-n
opção paraxargs
especificar quantos argumentos devem ser retirados do canal por vez. A configuração-n1
forçará oxargs
início de um novo processo para cada arquivo único. Esse pode ser um comportamento desejado se os arquivos forem muito grandes (como no caso desta pergunta) e houver um número relativamente pequeno de arquivos. No entanto, se os arquivos forem pequenos, a sobrecarga de iniciar um novo processo poderá prejudicar a vantagem do paralelismo, caso em que um-n
valor maior será melhor. Portanto, a-n
opção pode ser ajustada de acordo com o tamanho e o número do arquivo.Abordagem Paralela:
Outra maneira de fazer isso é usar a ferramenta Ole Tange GNU Parallel
parallel
, (disponível aqui ). Isso oferece maior controle de granulação fina sobre paralelismo e pode até ser distribuído por vários hosts (seria benéfico se seu diretório fosse compartilhado, por exemplo). A sintaxe mais simples usando paralelo será:find . -type f | parallel -j+1 grep mypattern
onde a opção
-j+1
instrui paralelamente a iniciar um processo além do número de núcleos em sua máquina (isso pode ser útil para tarefas limitadas de E / S, você pode até tentar aumentar em número).O paralelo também tem a vantagem
xargs
de realmente reter a ordem da saída de cada processo e gerar uma saída contígua. Por exemplo, comxargs
, se o processo 1 gerar uma linhap1L1
, digamos , o processo 2 gerar uma linhap2L1
, o processo 1 gerar outra linhap1L2
, a saída será:considerando que com
parallel
a saída deve ser:Isso geralmente é mais útil que a
xargs
saída.fonte
-n
em combinação com-P
. Caso contrário,xargs
pode não acabar gerando vários processos se houver dois poucos arquivos.grep
por arquivo. A menos que os arquivos sejam muito grandes e existam muito poucos, você provavelmente aumentará um pouco, pois gastará seu tempo iniciando e parando os processos grep em vez de pesquisar nos arquivos.Existem pelo menos duas maneiras de acelerar o grep em termos de CPU:
Se você estiver procurando por uma sequência fixa em vez de uma expressão regular, especifique o
-F
sinalizador;Se o seu padrão for apenas ASCII, use um código de idioma de 8 bits em vez de UTF-8, por exemplo
LC_ALL=C grep ...
.Isso não ajudará se o seu disco rígido for o gargalo; nesse caso, provavelmente o paralelismo também não ajudará.
fonte
man grep
"A chamada direta como egrep ou fgrep está obsoleta, mas é fornecida para permitir que aplicativos históricos que dependem deles sejam executados sem modificação". Não tenho certeza disso importa realmente, mas é o mesmo quegrep -F
Se o problema não estiver vinculado à E / S, você poderá usar uma ferramenta otimizada para processamento com vários núcleos.
Você pode dar uma olhada no sift ( http://sift-tool.org , aviso: eu sou o autor desta ferramenta) ou no pesquisador prateado ( https://github.com/ggreer/the_silver_searcher ).
o pesquisador prateado tem um limite de tamanho de arquivo de 2 GB se você usar um padrão de regex e não uma pesquisa de cadeia de espinha.
fonte