Ripgrep: ferramenta de busca mais rápida que grep, ag, Git grep e outras (2016)
(blog.burntsushi.net)- ripgrep (
rg) é uma ferramenta de busca em linha de comando baseada em Rust que combina a conveniência de busca de código no estilo do The Silver Searcher com o desempenho bruto no nível do GNU grep, com binários para Linux, Mac e Windows - Em 25 benchmarks, não houve ferramenta que superasse claramente o
ripgrepem desempenho e precisão tanto na busca em um único arquivo grande quanto em diretórios enormes, e o custo do suporte a Unicode também se manteve baixo - Inclui tratamento de
.gitignore, exclusão padrão de arquivos ocultos e binários, filtro por tipo de arquivo, suporte opcional a PCRE2, busca em vários encodings e arquivos compactados, além de filtros de pré-processamento, ampliando o uso prático de uma ferramenta de busca de código - As diferenças entre os testes no repositório do kernel Linux e no OpenSubtitles2016 dependem fortemente de otimização de literais, busca multipadrão com Teddy SIMD, Aho-Corasick, forma de decodificação UTF-8, contagem de linhas e custo do tratamento de
.gitignore - Ao buscar em paralelo por muitos arquivos pequenos, o memory map pode ficar mais lento, enquanto em um único arquivo grande pode ser vantajoso; por isso, o
ripgrepalterna entre busca com buffer intermediário e busca com memory map conforme o caso
A posição que o ripgrep buscou alcançar
ripgrepé uma ferramenta de busca em linha de comando que visa reunir a praticidade das ferramentas de busca de código com o desempenho das ferramentas da famíliagrep- Os alvos de comparação são
GNU grep,git grep,The Silver Searcher(ag),Universal Code Grep(ucg),The Platinum Searcher(pt)esift - Os benchmarks buscavam verificar três pontos principais
- não há ferramenta claramente superior ao
ripgreptanto em busca em arquivo único quanto em busca em diretórios de grande porte - ele oferece suporte adequado a Unicode sem exigir um grande custo de desempenho
- ao buscar em vários arquivos de uma vez, memory maps muitas vezes podem ser mais lentos, e não mais rápidos
- não há ferramenta claramente superior ao
- O autor é a pessoa que criou o
ripgrepe também o mecanismo de regex usado por ele, e reconhece que os benchmarks podem ser seletivos e enviesados
Recursos e comportamento padrão
- O nome do executável do
ripgrepérg - A busca padrão percorre recursivamente o diretório atual, respeita
.gitignoree ignora arquivos ocultos e arquivos binários - Também há suporte a
.rgignore, e os padrões de.rgignoretêm prioridade sobre os de.gitignore - Com
-u,-uue-uuu, é possível ampliar o escopo para ignorar arquivos de ignore, incluir arquivos ocultos e incluir arquivos bináriosrg -uuué semelhante agrep -a -r
- Há suporte a filtro por tipo de arquivo
rg -tpy foo: busca apenas em arquivos Pythonrg -Tjs foo: exclui arquivos JavaScript- é possível adicionar novas regras de tipo de arquivo com
--type-add
- Também oferece vários recursos do
grep- saída com contexto
- busca por vários padrões
- destaque com cores
- suporte completo a Unicode
- O mecanismo de regex padrão não oferece suporte a look-around nem backreference, mas esses recursos podem ser usados ao selecionar o mecanismo PCRE2 com
-P - Também há suporte a alguma detecção automática de UTF-16 e à especificação de encoding com
-E/--encoding- incluindo UTF-16, latin-1, GBK, EUC-JP e Shift_JIS
- Com
-z/--search-zip, há suporte à busca em arquivos compactados como gzip, xz, lzma, bzip2 e lz4 - Também há suporte a filtros arbitrários de pré-processamento, como extração de texto de PDF, descompressão adicional, descriptografia e detecção automática de encoding
Motivos para não usar
- Se a maior prioridade for portabilidade e disponibilidade em qualquer ambiente, o grep padrão, amplamente instalado e aderente a padrões, é a escolha mais adequada
- Se você depende de algum recurso específico ou bug presente em outra ferramenta, talvez o
ripgrepnão seja o ideal - Em alguns casos extremos de desempenho, outras ferramentas podem funcionar melhor
- Se não for possível instalar ou se a plataforma não tiver suporte, ele também não poderá ser usado
Estrutura de funcionamento das ferramentas da família grep
- Ferramentas de busca passam, em geral, por três etapas
- coletar os arquivos a serem pesquisados
- realizar a busca de fato
- exibir o resultado
- Como ferramentas da família
grepprecisam buscar bem em arquivos grandes, o desempenho do mecanismo de regex é importante - Ferramentas da família
ackprecisam processar rapidamente a navegação recursiva em diretórios e a aplicação de regras de ignore como.gitignore - O
ripgreptenta combinar as duas abordagens- mecanismo de regex rápido
- busca paralela
- filtragem dos alvos de busca
Coleta de arquivos e tratamento de ignore
- Em ferramentas da família
ack, é importante decidir rapidamente, a partir do diretório atual, quais arquivos serão pesquisados - O desempenho da varredura de diretórios é afetado pela quantidade de chamadas
statdesnecessárias - O
ripgrepusa um iterador recursivo de diretórios projetado para fazer o mínimo possível de chamadas de sistema - O tratamento de
.gitignoretem custo- é preciso procurar arquivos de ignore em cada diretório
- é preciso compilar os padrões de ignore
- é preciso aplicar os padrões a todos os caminhos candidatos
- O repositório do kernel Linux tinha 4.640 diretórios e 178 arquivos
.gitignore - O
ripgrepbusca oferecer suporte mais completo à semântica de.gitignore, dando prioridade ao padrão correspondente definido mais recentemente - O
ucgpode ser mais rápido por usar regras de glob baseadas em whitelist em vez de.gitignore, mas pode deixar passar arquivos com extensões que ele não conhece
Diferenças entre mecanismos de regex
- Em geral, mecanismos de regex se dividem em duas categorias
- baseados em backtracking: ricos em recursos, mas podem ficar exponencialmente lentos com certas entradas
- baseados em autômatos finitos: podem ter recursos mais limitados, mas oferecem garantia de tempo linear em relação ao tamanho do texto pesquisado
- Os mecanismos usados por cada ferramenta são os seguintes
- GNU grep,
git grep: mecanismo próprio baseado em autômatos finitos ripgrep: biblioteca regex de Rust, baseada em autômatos finitosag,ucg: baseados em PCRE com backtrackingpt,sift: biblioteca regex de Go, baseada em autômatos finitos
- GNU grep,
ageucg, por usarem PCRE, podem ficar expostos ao pior comportamento de backtracking- O padrão de exemplo
(a*)* cpode causar problemas em ferramentas baseadas em PCRE, mas as outras ferramentas dos benchmarks o processam sem dificuldade
Otimização de literais e SIMD
- Em buscas por strings simples, a otimização de busca por literais pode se tornar mais importante do que o mecanismo de regex em si
- Boyer-Moore é um algoritmo clássico de busca de substring, e pode usar rotinas como
memchrpara localizar rapidamente posições candidatas - Implementações de
memchrmuitas vezes usam instruções SIMD para examinar 16 bytes de uma vez, alcançando vazões de vários GB/s - A biblioteca regex de Rust extrai agressivamente literais de prefixo e sufixo dos padrões
foo|bar(a|b)c[ab]foo[yz](foo)?bar(foo)*bar(foo){3,6}
- Se a regex inteira puder ser decomposta em um único literal ou em uma alternância de literais, o mecanismo principal de regex pode nem ser usado
- O
ripgreptambém extrai literais internos aproveitando a característica de saída por linha- exemplo: em
\w+foo\d+, ele encontra primeirofooe depois valida com regex apenas as linhas candidatas
- exemplo: em
- Para busca por vários literais, o GNU grep usa um algoritmo semelhante ao Commentz-Walter, enquanto a regex de Rust usa Aho-Corasick ou o algoritmo Teddy SIMD
- Teddy é um algoritmo de busca multipadrão baseado em SIMD vindo do Intel Hyperscan, e é uma das otimizações centrais que permitem ao
ripgrepsuperar o GNU grep
Método de busca: evitando busca linha por linha
- Uma implementação ingênua leria o arquivo linha por linha e aplicaria o padrão em cada linha, mas isso é ineficiente porque, na maioria das buscas, correspondências são raras
- Ferramentas de busca normalmente pesquisam grandes buffers de bytes de uma vez
- mapeando o arquivo com memory map
- lendo o arquivo inteiro na memória
- fazendo busca incremental com um buffer intermediário de tamanho fixo
ripgrep, GNU grep egit grepoferecem suporte a busca incremental, o que permite aplicar isso tanto a arquivos quanto a streams- A busca incremental é difícil de implementar
- cálculo de números de linha
- tratamento quando o buffer termina no meio de uma linha
- tratamento de linhas longas
- tratamento de invert match
- tratamento da exibição de contexto ao redor da correspondência
- O
ripgrepassume essa complexidade de implementação e usa busca incremental, mostrando nos benchmarks resultados mais rápidos do que memory map ao pesquisar muitos arquivos pequenos
Saída e paralelismo
- Em buscas paralelas, se cada thread escrever a saída imediatamente, os resultados de arquivos diferentes podem se misturar
- Todas as ferramentas de busca de código com paralelismo escrevem os resultados da busca em um buffer intermediário na memória e serializam apenas a etapa de saída
- Esse método permite que as threads de busca executem a busca real em paralelo
- A desvantagem é que o uso de memória pode crescer em casos como um arquivo de 2 GB em que todas as linhas dão match
- O
ripgrepescreve diretamente emstdout, sem buffer intermediário, ao buscar emstdinou em um único arquivo
Metodologia de benchmark
- Os benchmarks são divididos com base nos problemas do usuário final
- busca em grandes repositórios de código
- busca em um único arquivo grande
- Os padrões de busca são tendenciosos para literais simples, alternation e expressões regulares leves
- Como o comportamento padrão varia entre as ferramentas, tentou-se alinhar condições como número de linha, Unicode,
.gitignoree whitelist para uma comparação justa - As versões avaliadas no benchmark foram as seguintes
ripgrepv0.1.2- GNU grep v2.25
git grepv2.7.4agcommitcda635, PCRE 8.38ucgcommit487bfb, PCRE 10.21 JITptcommit509368siftcommit2d175c
- O
ackfoi excluído por ser muito mais lento que as outras ferramentas na época - O runner de benchmark é o
benchsuite, que exige Python 3.5 ou superior, e está incluído no repositório doripgrep - Cada comando executa 3 warm-ups antes da medição, para que o corpus seja carregado no page cache do sistema operacional
- Cada comando é medido 10 vezes, e são registrados a média e o desvio padrão
- O ambiente de execução foi Amazon EC2
c3.2xlarge, Ubuntu 16.04, Xeon E5-2680 2.8GHz, 16 GB de memória e SSD de 80 GB - Também foram publicados o log de configuração, os resultados resumidos e o CSV bruto
Resultados de busca no código do kernel Linux
- O benchmark de busca em código foi executado no repositório do kernel Linux compilado, commit
d0acc7 - O motivo de usar o repositório do kernel compilado é que os artefatos de build permanecem no repositório e podem afetar tanto a relevância dos resultados quanto o desempenho
- Em
linux_literal_default, a busca pelo literal simplesPM_RESUMErevela as diferenças no comportamento padrão de cada ferramentargrespeita.gitignoree ignora arquivos ocultos e bináriosageptfazem algo parecido, mas contam o número de linhasucgnão lê.gitignoree busca com base em whitelistsiftpor padrão busca em quase tudogit greptem a vantagem de obter do índice do git o conjunto de arquivos a pesquisar
- Respeitar
.gitignoreaumenta a relevância dos resultados, mas pode ter custo de desempenho - Em
linux_literal,rg (whitelist)teve desempenho quase igual aoucg, erg (ignore)ficou em nível parecido comgit grep rg (ignore) (mmap)eag (ignore) (mmap)ficaram mais lentos com uso de memory map, e nas mesmas condiçõesrg (ignore)foi muito mais rápido- Mesmo em máquina local, as versões com memory map foram mais lentas, embora a diferença tenha sido menor do que na EC2
Unicode e busca sem distinção entre maiúsculas e minúsculas
- Em
linux_literal_casei,ptficou muito mais lento ao tratar-icomo(?i)da regexp do Go siftperdeu menos desempenho porque usa uma abordagem de converter o padrão e o bloco pesquisado para minúsculas, mas essa otimização só cobre maiúsculas e minúsculas ASCII e é incorreta para Unicode- O
ripgreptransforma a busca case-insensitive em combinações literais quando possível e usa Teddy para localizar rapidamente posições candidatas - A busca
\wAhemlinux_unicode_wordverifica se\wcom reconhecimento de Unicode encontra resultados comoµAh - Só
rgegit greppermitiam alternar Unicode;ag,pt,sifteucgusavam\wapenas ASCII git grepteve um grande custo de desempenho ao ativar suporte a Unicode, mas oripgrepquase não perdeu desempenho- O
ripgrepincorpora a decodificação UTF-8 na máquina de estados finitos e faz match diretamente sobre strings de bytes UTF-8, sem etapa separada de decodificação
Diferenças conforme a complexidade da expressão regular
- Em regex com sufixo literal como
[A-Z]+_RESUME,rgeucgusam_RESUMEpara localizar candidatos rapidamente - Em alternation literal como
ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT, oripgrepusa Teddy e pode nem acionar o engine principal de regex - Mesmo em alternation sem distinção entre maiúsculas e minúsculas, o
ripgrepcria prefixes com combinações de maiúsculas e minúsculas, usa Teddy para localizar candidatos e valida apenas os candidatos com a regex completa - Na busca por
\p{Greek}, apenas Rust regex e Go regex suportavam essa propriedade Unicode, ergfoi muito mais rápido queptesift - Na busca por
\p{Greek}sem distinção entre maiúsculas e minúsculas,siftnão conseguiu reportar matches, eptnão tratou corretamente as regras de maiúsculas e minúsculas em Unicode - Em padrões sem literais, como
\w{5}\s+..., o desempenho do engine de regex aparece diretamentergcontinuou relativamente rápido mesmo com suporte a Unicode ativadogit greppagou um custo alto com suporte a Unicode- O DFA Unicode lida com um conjunto de estados NFA muito maior do que o DFA ASCII; o exemplo citado é de cerca de 250 estados NFA para ASCII contra cerca de 77.000 para Unicode
Busca em um único arquivo grande
- O benchmark de arquivo único usa a amostra OpenSubtitles2016
- a amostra em inglês tem cerca de 1 GB
- a amostra em russo tem cerca de 1,6 GB
- Nessa área, o desempenho do engine de regex e as otimizações para literais se tornam mais importantes
- Em
subtitles_literal, orgfoi o mais rápido tanto na busca porSherlock Holmesquanto porШерлок Холмс - O
ripgreptenta escolher um byte raro em literais para usar commemchr- implementações padrão de Boyer-Moore normalmente usam o último byte para buscar candidatos
- o
rgtenta escolher um byte mais raro para pular por mais tempo dentro de um loop otimizado com SIMD
- Em UTF-8, muitos caracteres do padrão russo começam com
\xD0ou\xD1, então buscar pelo primeiro byte pode ser ineficiente - O
rgusa uma tabela de frequência pré-computada de 256 bytes e prefere bytes mais raros em vez de\xD0e\xD1 - Em um único arquivo grande, como o memory map só precisa ser criado uma vez, a busca com memory map do
rgfoi cerca de 25% mais rápida querg (no mmap)
Unicode e alternation em arquivo único
- Em
subtitles_literal_casei, orgé rápido mesmo tratando corretamente a busca Unicode sem distinção entre maiúsculas e minúsculas - O GNU grep paga um custo alto em buscas Unicode sem distinção entre maiúsculas e minúsculas
- Na busca em russo sem distinção entre maiúsculas e minúsculas,
grep (ASCII)parece na prática ignorar-i, eagreporta 0 matches - Em
subtitles_alternate, a busca por alternation de vários nomes de personagens foi mais rápida comrgtanto em inglês quanto em russo - Na alternation em inglês,
rgfoi cerca de uma ordem de grandeza mais rápido que o GNU grep - Em
subtitles_alternate_casei, orgficou muito mais lento que antes, mas ainda superou as outras ferramentas em inglês - Nesse caso, o número de candidatos literais fica grande demais para o Teddy, então o
rgtroca Teddy por Aho-Corasick - O
ripgrepusa um Aho-Corasick “advanced” baseado em tabela de transição, realizando uma transição por byte de entrada
inner literals e padrões sem literais
- Padrões como
\w+\s+Holmes\s+\w+foram construídos para evitar a otimização de literais de prefixo/sufixo, mas ainda podem aproveitar o literal internoHolmes ripgrepe GNU grep fazem a otimização de inner literal- O
ripgrepusa oregex-syntaxdo Rust regex para extrair literais da AST do padrão - Na versão em russo
\w+\s+Холмс\s+\w+, só ferramentas com suporte adequado a Unicode conseguiam produzir resultados relevantes - Em padrões longos como
\w{5}\s+..., sem nenhum literal, orgficou entre os mais rápidos em inglês, e a versão do GNU grep com suporte a Unicode foi excluída por levar mais de 90 segundos em inglês e mais de 4 minutos em russo - O
ripgrepmantém o suporte a Unicode e ainda garante desempenho ao incorporar a decodificação UTF-8 no DFA
Benchmarks adicionais
everythingé um teste irrealista que faz correspondência de todas as linhas com.*no repositório do Linuxrgreportou 22.065.361 linhas em 1,081 sageptnão reportaram todas as linhas, sugerindo que têm limite de correspondências
nothingé um teste que aplica invert match a.*para não reportar nenhuma linhargmarcou 0,302 s egit grep0,905 spteucgnão oferecem suporte a busca invertida
contextimprime 2 linhas de contexto ao redor deSherlock Holmesem um corpus de legendas em inglêsrgficou em 0,612 s esiftem 0,717 s, com desempenho parecidoucgnão oferece suporte a esse recurso
hugebuscaSherlock Holmesem todas as 9,3 GB de legendas em inglêsrgmarcou 1,786 s, GNU grep 5,119 s esift3,047 sucgreportou incorretamente apenas 1.543 linhas na condição de contagem de linhas, e suspeita-se que tenha tido problemas ao buscar em arquivos maiores que 2 GB
Conclusão
- O
ripgrepnem sempre venceu todos os benchmarks na busca no repositório do kernel Linux, mas era difícil dizer que qualquer outra ferramenta tinha vantagem clara em desempenho e precisão - O
git greppodia ficar alguns milissegundos à frente em certos casos simples, mas quando o padrão ficava mais complexo ou era necessário Unicode, houve casos em que oripgrepficou muito à frente - Os fatores a seguir contribuíram para o desempenho do
ripgrepem busca de código- varredura rápida de diretórios com foco em minimizar chamadas a
stat - correspondência de globs do
.gitignorecomRegexSet - distribuição de trabalho com uma fila work stealing Chase-Lev
- a escolha de não usar mapeamento de memória ao buscar em muitos arquivos pequenos
- um mecanismo de expressões regulares rápido
- varredura rápida de diretórios com foco em minimizar chamadas a
- Na busca em arquivo único, o
ripgrepfoi o mais rápido em todos os principais benchmarks ou ficou muito à frente - No desempenho em arquivo único, influem
memchrbaseado em bytes esparsos, Teddy SIMD, Aho-Corasick e DFA com decodificação UTF-8 embutida - Nos benchmarks que exigiam recursos Unicode, só
rg, GNU grep egit grepmostraram suporte relevante, e GNU grep egit grepem geral pagavam um custo de desempenho alto - O mapeamento de memória foi desvantajoso em buscas paralelas em muitos arquivos pequenos no Linux x86_64, vantajoso na busca em um único arquivo grande, e pode ter penalidade extra em ambientes de VM
1 comentários
Opiniões no Hacker News
É definitivamente rápido, e continuo recomendando a combinação com fzf
Uso como uma função do PowerShell: primeiro procuro com
ripgrep, depois aplico uma busca fuzzy sobre os arquivos+textos resultantes e mostro o contexto combatEm projetos com vários repositórios misturados, dá para ir estreitando muito rápido quando “sei que está em algum lugar, mas não sei exatamente a localização ou o nome”
Esse método veio de https://github.com/junegunn/fzf/blob/master/ADVANCED.md, e mesmo que você não use tudo, vale dar uma olhada para tirar ideias
fzfDá para fazer busca fuzzy não só em arquivos de texto, mas também em vários formatos de arquivo, como PDF e zip
Mais detalhes em https://github.com/phiresky/ripgrep-all/wiki/fzf-Integration
A ideia é escolher um resultado de
rgcomfzf, fazer o parsing do arquivo e do número da linha selecionados e abrir com$EDITOR +"${linenumber}" "$file"É como moer café à mão em vez de usar um moedor elétrico
fzf, dá para escolher muitos arquivos para adicionar ao Git e pular alguns delesSe você colocar
fza = "!git ls-files -m -o --exclude-standard | fzf -m --print0 | xargs -0 git add"em[alias]nogitconfig,git fzamostra a lista de arquivos modificados ou ainda não adicionados, e você alterna os itens com espaço enquanto avança para o próximoEsse alias e fzf+fd aceleram bastante parte do fluxo de trabalho
Há também um guia com itens para colocar na configuração do zsh no macOS: https://gist.github.com/aclarknexient/0ffcb98aa262c585c49d4b...
ripgrepquase do mesmo jeitoEm uma codebase com centenas de repositórios, uso como ponto de partida para ir estreitando arquivos ou projetos, e depois me aprofundo
No Emacs, uso
ripgrepcom os pacotes project.el e dumb-jumpTalvez não seja a forma mais popular, mas a experiência geral é bem satisfatória
Basta instalar
dumb-jumpcompackage-installe configurar apenas(add-hook 'xref-backend-functions #'dumb-jump-xref-activate)Em projetos Python, quando você procura a definição de um identificador com
M-.ouC-u M-., odumb-jumpexecuta um comandorgadequado ao projeto e ao tipo de arquivo atuais e mostra os resultados no buffer XrefEle também suporta
age, se não houveragnemrg, volta paragrep, mas ao procurar no diretório home inteiro pode ser lento, como esperadoripgrepcom bastante facilidadeNão é obrigatório ter um pacote externo; para usar no lugar do
greplento em diretórios grandes, basta configurar(setq xref-search-program 'ripgrep)Assim, uma busca de projeto como
C-x p g foo RETé executada no projeto atual na formarg -i --null -nH --no-heading --no-messages -g '!*/' -e fooOs resultados aparecem no buffer Xref, o que facilita ir para a próxima/anterior ocorrência, pular para o código-fonte e exibir em uma janela dividida com teclas como
n,p,RET,C-oripgrep, olhando para essa expressão regular, embora eu não a tenha executado diretamente, acho que dá para remover a flag --pcre2Também parece que a segunda e a terceira asserções
\bpodem ser removidas, embora a primeira talvez seja necessáriaripgrepe também tem bindings doevil-collection, então dá para usar de forma satisfatória: https://github.com/Wilfred/deadgrepNessas situações, antigamente eu teria usado
rgrepO interessante é que a busca do VS Code agora também funciona com
ripgreppor meio de um wrapper em Node.jshttps://www.npmjs.com/package/@vscode/ripgrep
ripgrep, isso é ótimoDá para encontrar o binário
rgdentro do caminho de instalação do VS. Pelo menos no meu ambiente corporativo Windows isso foi possívelUso
ripgrephá cerca de 2 anos e agora ele se tornou uma ferramenta indispensávelO principal motivo para eu ter migrado do
grepfoi a facilidade de usoPor padrão, ele respeita as regras do
.gitignoree ignora arquivos/diretórios ocultos e arquivos binários, entãorg search_term directoryé muito melhor do que o comandogrepcorrespondente; o ganho de velocidade é um bônusQuando uma correspondência é longa demais e bagunça o terminal, costumo usar a opção -M, como em
-M 1000-Mé realmente excelenteÉ especialmente prático para ignorar resultados de arquivos minified que você não quer ver, e também é bom pesquisar só arquivos de uma extensão específica com a opção -g, como em
-g *.csO fato de ser um binário portátil e standalone também é útil: quando trabalho em uma máquina nova, coloco o executável e defino o alias de
greppararg; assim, mesmo digitandogreppor hábito, quem roda é orgIsso talvez ainda seja verdade em 2023, mas o problema é que as ferramentas paralelizadas que substituem o
grep, comoripgrepouag, são tão mais rápidas que ogreptradicional que pequenas diferenças de velocidade entre elas dificilmente servem como critério de distinçãoUso
agdentro do Emacs em uma base de código de 900 mil linhas e, em um Ryzen Threadripper 2950X de 16 núcleos, ele termina praticamente na horaNão sinto necessidade de reduzir algo abaixo de 1 segundo para “um pouco mais abaixo de 1 segundo”
A característica central das novas ferramentas do tipo
grepnão é a velocidade; elas precisam ser avaliadas e comparadas de outras formasO
agtem penhascos de desempenho bastante grandes, e isso também aparece no post do blogMas a carga de trabalho varia de pessoa para pessoa, então em alguns casos a diferença de desempenho pode não importar
900 mil linhas não é tanta coisa assim e, para consultas simples, a maioria das ferramentas do tipo
grepque não sejam ingênuas processa isso muito rapidamentePor outros critérios de comparação, o
agestá quase em suporte de vida e parece que quase foi removido do Debian, até alguém o salvar: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=999962O post do blog também compara suporte a Unicode, e o
agpraticamente não tem suporte a Unicode. Pode não ser importante para todo mundo, mas é um critério não relacionado a desempenho bastante válidoO tempo de busca leva tanto quanto o tempo para carregar os arquivos do disco, e as diferenças depois disso dificilmente são significativas
Se os arquivos estão em cache, o tempo para navegar pelo sistema de arquivos e digitar o comando domina mais que o tempo de busca, então, de novo, fica difícil a diferença de desempenho ser relevante
O título precisa de (2016)
Isto é o anúncio original, não uma informação nova
“Ripgrep – A new command line search tool” https://news.ycombinator.com/item?id=12564442 (740 points | Sept 23, 2016 | 209 comments) — também há discussão sobre velocidade
“Ripgrep is faster (2016)” https://news.ycombinator.com/item?id=17941319 (98 points | Sept 8, 2018 | 40 comments)
Não é mais rápido que o
qgrepO modo de funcionamento dos dois é bem diferente, e o
qgrepé baseado emre2, mas a velocidade vem por causa do índiceEm repositórios grandes de arquivos, faz mais sentido usar
qgrepcom índice do que varrer todos os arquivos toda vez, e fico curioso por que as pessoas esquecem a opçãoqgrepDito isso, se você precisa de correspondência multilinha em UTF-8, acho que o
ripgrepprecisa recorrer a outra biblioteca PCRE2 e, por isso, não fica tão rápidoripgrep, é verdade que oqgreptem vantagem sobre ferramentas sem indexação por usar indexaçãoEm compensação, é preciso configurar e manter o índice, então a UX não é tão simples quanto “simplesmente executar a busca”
O motivo de as pessoas não usarem
qgrepé parecido com o motivo de não usaremripgrepdizendo “para mim, grep já é rápido o suficiente”Em alvos de busca pequenos, muitas vezes não se percebe a diferença de velocidade entre
ripgrepegrep, ou entreqgreperipgrepSe o
ripgreptermina uma busca no kernel Linux em menos de 100 ms, trocar para uma ferramenta indexada em uso interativo padrão pode ou não ser inconveniente o bastante para valer a pena, dependendo do caso, mas em geral não seráJá pensei na ideia de adicionar indexação ao
ripgrep: https://github.com/BurntSushi/ripgrep/issues/1497E busca multilinha não exige PCRE2. O motor de expressões regulares padrão também tem suporte a Unicode, e o suporte a busca multilinha permanece mesmo em builds sem PCRE2
Depois que migrei do
ripgreppara o ugrep, não olhei mais para trásA velocidade é parecida, mas ele tem correspondência aproximada, uma TUI útil para revisão de código e também consegue buscar dentro de PDFs e arquivos compactados
Também é conveniente poder usar opcionalmente a sintaxe de busca do Google
https://ugrep.com
ripgrep, mas recentemente acabei encontrando ougreppor causa de um recurso que oripgrepnão tem: buscar dentro de arquivos zip compactadosDá para buscar sem descompactar no disco
Trabalho com corpora compactados formados por milhões de pequenos arquivos de texto, e é ótimo não precisar extrair tudo para o sistema de arquivos. Alguns sistemas de arquivos sofrem nessa escala
Sou grato pelas duas ferramentas e agradeço aos respectivos autores
grep, a maioria dos resultados acabe tentando vender alguma coisaugrepe doripgrepdiscutiram no Reddit por alguns anosPor exemplo https://www.reddit.com/r/programming/comments/120wqvr/ripgre...
É só uma conversa sobre ferramentas open source, mas pareceu meio estranho
fzfPara mim, parece difícil superar a configurabilidade e a flexibilidade do
fzfO recurso matador parece ser a compatibilidade com as opções de linha de comando existentes do grep
É bem bom não precisar aprender um conjunto de opções completamente novo
Fico me perguntando por que o
grepnão é substituído ou melhoradoAcho que esse assunto já está meio antigo
Inércia, compatibilidade, resistência à mudança, coisas como o dilema do inovador. Não estou dizendo isso de forma negativa; tudo isso também se aplica a mim
Sobre compatibilidade, veja o FAQ: https://github.com/BurntSushi/ripgrep/blob/master/FAQ.md#pos...
Ela é confortável, combina bem com meu ambiente de trabalho ao redor, e não há motivo para trocar e ajustar tudo de novo
A analogia só vai até o ponto de eu já ter uma cadeira tipo Razer por perto, servindo para pendurar roupas
xyz, e ele precisa aceitar estes argumentos e se comportar exatamente assim”ripgrepSe a ideia for trocar o próprio comando
greppor outro utilitário, parece que muita coisa quebraria em comparação ao valor obtidoQuem quer um
grepmais rápido usa outra ferramenta, e quem usa ogrepexistente continua usando; então isso já está perto do estado idealgrepé uma ferramenta de uso geral para encontrar texto em todos os tipos de arquivo, e está cravado no padrão UNIXAlguns programadores o usam para busca em código-fonte, mas outras pessoas o usam para buscas de texto sem relação com código-fonte ou em scripts, esperando que ele nunca trave
Já o
ripgrepé uma ferramenta especializada e bastante opinativa, projetada principalmente para buscar em repositórios de código-fonteNão há muito espaço para tornar a busca de texto de uso geral mais rápida. Usar
mmap()traz risco de travamento em arquivos truncados; reduzir a expressividade das expressões regulares poderia deixá-la mais rápida; e também seria possível abandonar o suporte a todos os locales e conjuntos de caracteres e hardcodar apenas UTF-8/UTF-16, mas não se deve fazer issoProcurei no Portage e parece haver também uma versão que lida com outros documentos, como PDFs e arquivos doc
https://github.com/phiresky/ripgrep-all