Ripgrep: una herramienta de búsqueda más rápida que grep, ag y Git grep (2016)
(blog.burntsushi.net)- ripgrep(
rg) es una herramienta de búsqueda en línea de comandos basada en Rust que combina la comodidad de búsqueda de código al estilo de The Silver Searcher con el rendimiento bruto de GNU grep, y ofrece binarios para Linux, Mac y Windows - En 25 benchmarks, no hubo ninguna herramienta que superara claramente a
ripgreptanto en rendimiento como en precisión, ni en búsquedas sobre un solo archivo grande ni en directorios masivos, y el costo del soporte para Unicode también se mantuvo bajo - Amplía el alcance práctico de las herramientas de búsqueda de código al incluir manejo de
.gitignore, exclusión predeterminada de archivos ocultos y binarios, filtros por tipo de archivo, soporte opcional para PCRE2, búsqueda en múltiples codificaciones y archivos comprimidos, e incluso filtros de preprocesamiento - La diferencia entre los experimentos con el repositorio del kernel de Linux y OpenSubtitles2016 depende en gran medida de la optimización de literales, la búsqueda multipatrón Teddy SIMD, Aho-Corasick, el método de decodificación UTF-8, el conteo de líneas y el costo de procesar
.gitignore - Al buscar en paralelo muchos archivos pequeños, el mapeo de memoria puede volverse más lento, mientras que en un solo archivo grande puede ser ventajoso; por eso
ripgrepusa según el caso búsqueda con búfer intermedio o búsqueda con mapeo de memoria
La posición a la que apuntaba ripgrep
ripgrepes una herramienta de búsqueda en línea de comandos que busca combinar la comodidad de las herramientas de búsqueda de código con el rendimiento de las herramientas tipogrep- Los objetos de comparación son
GNU grep,git grep,The Silver Searcher(ag),Universal Code Grep(ucg),The Platinum Searcher(pt)ysift - Los benchmarks buscaban confirmar tres puntos clave
- No hay ninguna herramienta claramente superior a
ripgreptanto en búsquedas sobre un solo archivo como en búsquedas sobre directorios de gran tamaño - Ofrece soporte para Unicode correcto sin exigir un gran costo de rendimiento
- Al buscar varios archivos a la vez, el mapeo de memoria puede ser, por lo general, más lento en lugar de más rápido
- No hay ninguna herramienta claramente superior a
- El autor es quien creó
ripgrepy el motor de expresiones regulares en el que se basa, y aclara que los benchmarks pueden estar seleccionados de forma sesgada
Funciones y comportamiento predeterminado
- El nombre del ejecutable de
ripgrepesrg - La búsqueda predeterminada recorre recursivamente el directorio actual, respeta
.gitignorey omite archivos ocultos y binarios - También soporta
.rgignore, y los patrones de.rgignoretienen prioridad sobre los de.gitignore - Con
-u,-uuy-uuuse puede ampliar el alcance para ignorar archivos de ignore, incluir archivos ocultos e incluir archivos binariosrg -uuues similar agrep -a -r
- Soporta filtros por tipo de archivo
rg -tpy foo: busca solo en archivos Pythonrg -Tjs foo: excluye archivos JavaScript- Se pueden agregar nuevas reglas de tipo de archivo con
--type-add
- También ofrece varias funciones de
grep- salida con contexto
- búsqueda de múltiples patrones
- resaltado con color
- soporte completo para Unicode
- El motor de expresiones regulares predeterminado no soporta look-around ni backreference, pero al elegir el motor PCRE2 con
-Pse pueden usar esas funciones - También soporta detección automática parcial de UTF-16 y especificación de codificación mediante
-E/--encoding- Incluye UTF-16, latin-1, GBK, EUC-JP, Shift_JIS y otras
- Con
-z/--search-zippermite buscar dentro de archivos comprimidos como gzip, xz, lzma, bzip2 y lz4 - También admite filtros arbitrarios de preprocesamiento como extracción de texto de PDF, descompresión adicional, descifrado y detección automática de codificación
Razones para no usarlo
- Si la máxima prioridad es la portabilidad y poder usarlo en cualquier parte, grep, al ser estándar y estar ampliamente instalado, puede ser la mejor opción
- Si dependes de alguna función o bug específico presente en otras herramientas, puede que
ripgrepno sea adecuado - En algunos casos límite de rendimiento, otras herramientas pueden comportarse mejor
- Si no se puede instalar o no hay soporte para la plataforma, tampoco se podrá usar
Estructura de funcionamiento de las herramientas tipo grep
- Las herramientas de búsqueda pasan, en general, por tres etapas
- recopilar los archivos a buscar
- realizar la búsqueda real
- mostrar los resultados
- Las herramientas tipo
grepdeben buscar bien en archivos grandes, por lo que el rendimiento del motor de expresiones regulares es importante - Las herramientas tipo
ackdeben procesar rápido el recorrido recursivo de directorios y la aplicación de reglas de ignore como.gitignore ripgrepintenta combinar ambos enfoques- motor de expresiones regulares rápido
- búsqueda en paralelo
- filtrado de objetivos de búsqueda
Recolección de archivos y manejo de ignore
- En las herramientas tipo
ack, es importante decidir rápidamente qué archivos buscar desde el directorio actual - El rendimiento del recorrido de directorios se ve afectado por la cantidad de llamadas
statinnecesarias ripgrepusa un iterador recursivo de directorios orientado a minimizar las llamadas al sistema- Procesar
.gitignoretiene un costo- hay que encontrar archivos de ignore en cada directorio
- hay que compilar los patrones de ignore
- hay que aplicar los patrones a todas las rutas candidatas
- El repositorio del kernel de Linux tenía 4,640 directorios y 178 archivos
.gitignore ripgrepintenta soportar de forma más completa la semántica de.gitignorey da prioridad al patrón coincidente definido más recientementeucgpuede ser más rápido porque usa reglas glob basadas en listas blancas en lugar de.gitignore, pero puede pasar por alto archivos con extensiones desconocidas
Diferencias entre motores de expresiones regulares
- Los motores de expresiones regulares se dividen, en general, en dos grupos
- basados en backtracking: tienen muchas funciones, pero pueden volverse exponencialmente lentos con algunas entradas
- basados en autómatas finitos: pueden tener funciones más limitadas, pero garantizan tiempo lineal respecto a la longitud del texto de búsqueda
- Los motores por herramienta son los siguientes
- GNU grep,
git grep: motores propios basados en autómatas finitos ripgrep: biblioteca Rust regex, basada en autómatas finitosag,ucg: basados en PCRE con backtrackingpt,sift: biblioteca Go regex, basada en autómatas finitos
- GNU grep,
agyucg, al usar PCRE, pueden quedar expuestos al peor comportamiento del backtracking- El patrón de ejemplo
(a*)* cpuede causar problemas en herramientas basadas en PCRE, pero las demás herramientas evaluadas en los benchmarks lo procesan sin problemas
Optimización de literales y SIMD
- En búsquedas de cadenas simples, la optimización de búsqueda de literales puede ser más importante que el motor de expresiones regulares
- Boyer-Moore es un algoritmo clásico de búsqueda de subcadenas, y puede usar rutinas como
memchrpara encontrar rápidamente posiciones candidatas - Las implementaciones de
memchra menudo inspeccionan 16 bytes a la vez con instrucciones SIMD, y pueden alcanzar un rendimiento de varios GB/s - La biblioteca Rust regex extrae activamente literales de prefijo y sufijo del patrón
foo|bar(a|b)c[ab]foo[yz](foo)?bar(foo)*bar(foo){3,6}
- Si toda la expresión regular puede descomponerse en un solo literal o en una alternancia de literales, puede incluso no usar en absoluto el motor principal de expresiones regulares
ripgreptambién extrae literales internos aprovechando que muestra resultados por línea- Ejemplo: en
\w+foo\d+, primero encuentrafooy luego valida con la expresión regular solo las líneas candidatas
- Ejemplo: en
- Para buscar múltiples literales, GNU grep usa un algoritmo similar a Commentz-Walter, mientras que Rust regex usa Aho-Corasick o el algoritmo Teddy SIMD
- Teddy es un algoritmo de búsqueda multipatrón basado en SIMD proveniente de Intel Hyperscan, y es una de las optimizaciones clave por las que
ripgrepsupera a GNU grep
Método de búsqueda: evitar la búsqueda línea por línea
- Una implementación ingenua lee el archivo línea por línea y aplica el patrón a cada línea, pero como en la mayoría de las búsquedas las coincidencias son escasas, eso resulta ineficiente
- Las herramientas de búsqueda suelen buscar sobre grandes búferes de bytes de una sola vez
- mapear el archivo en memoria
- leer el archivo completo en memoria
- búsqueda progresiva con un búfer intermedio de tamaño fijo
ripgrep, GNU grep ygit grepsoportan búsqueda progresiva, por lo que puede aplicarse tanto a archivos como a streams- La búsqueda progresiva es difícil de implementar
- cálculo del número de línea
- manejo de casos en que el búfer termina a mitad de línea
- manejo de líneas largas
- manejo de invert match
- manejo de la salida de contexto alrededor de las coincidencias
ripgrepasume la complejidad de implementación y usa búsqueda progresiva, y en los benchmarks muestra resultados más rápidos que el mapeo de memoria al buscar muchos archivos pequeños
Salida y paralelismo
- En la búsqueda en paralelo, si cada hilo imprime de inmediato, los resultados de distintos archivos pueden mezclarse
- Todas las herramientas de búsqueda de código en paralelo escriben primero los resultados en un búfer intermedio en memoria y serializan solo la etapa de salida
- Este enfoque permite que los hilos de búsqueda realicen la búsqueda real en paralelo
- La desventaja es que el uso de memoria puede crecer, por ejemplo, con un archivo de 2 GB donde todas las líneas hacen match
ripgrepescribe directamente astdoutsin búfer intermedio cuando busca enstdino en un solo archivo
Metodología de benchmarks
- Los benchmarks se dividen según el problema del usuario final
- búsqueda en repositorios de código grandes
- búsqueda en un solo archivo grande
- Los patrones de búsqueda están sesgados hacia literales simples, alternation y expresiones regulares ligeras
- Como el comportamiento predeterminado varía entre herramientas, se intentó igualar condiciones como números de línea, Unicode,
.gitignorey listas blancas para hacer comparaciones justas - Las versiones evaluadas en los benchmarks fueron las siguientes
ripgrepv0.1.2- GNU grep v2.25
git grepv2.7.4agcommitcda635, PCRE 8.38ucgcommit487bfb, PCRE 10.21 JITptcommit509368siftcommit2d175c
ackquedó fuera porque en ese momento era mucho más lento que las otras herramientas- El runner de benchmarks es
benchsuite, que requiere Python 3.5 o superior, y está incluido en el repositorio deripgrep - Antes de medir, cada comando ejecuta 3 warm-ups para que el corpus quede cargado en el page cache del sistema operativo
- Cada comando se mide 10 veces y se registran el promedio y la desviación estándar
- El entorno de ejecución fue Amazon EC2
c3.2xlarge, Ubuntu 16.04, Xeon E5-2680 2.8GHz, 16 GB de memoria y SSD de 80 GB - También se publicaron el log de configuración, los resultados resumidos y el CSV en bruto
Resultados de búsqueda en el código del kernel de Linux
- El benchmark de búsqueda en código se ejecutó sobre un repositorio del kernel de Linux compilado, commit
d0acc7 - La razón para usar un repositorio del kernel compilado es que los artefactos de compilación pueden permanecer en el repositorio y afectar tanto la relevancia de los resultados como el rendimiento
- En
linux_literal_default, la búsqueda del literal simplePM_RESUMEmuestra las diferencias de comportamiento predeterminado entre las herramientasrgrespeta.gitignorey omite archivos ocultos y binariosagyptson similares, pero cuentan el número de líneasucgno lee.gitignorey busca con base en una lista blancasiftbusca casi todo por defectogit greptiene la ventaja de obtener el conjunto de archivos a buscar desde el índice de git
- Respetar
.gitignoremejora la relevancia de los resultados, pero puede tener un costo en rendimiento - En
linux_literal,rg (whitelist)mostró un rendimiento casi igual al deucg, yrg (ignore)quedó en un nivel similar al degit grep rg (ignore) (mmap)yag (ignore) (mmap)fueron más lentos por usar memory map, y en las mismas condicionesrg (ignore)fue mucho más rápido- En una máquina local, las versiones con memory map también fueron más lentas, aunque la diferencia fue menor que en EC2
Unicode y búsqueda sin distinguir mayúsculas y minúsculas
- En
linux_literal_casei,ptse volvió mucho más lento al procesar-icomo(?i)del regexp de Go siftse volvió menos lento porque convierte el patrón y el bloque de búsqueda a minúsculas, pero esa optimización solo maneja mayúsculas y minúsculas ASCII y no es correcta para Unicoderipgrepconvierte la búsqueda case-insensitive en combinaciones literales cuando es posible y usa Teddy para encontrar rápidamente posiciones candidatas- La búsqueda
\wAhenlinux_unicode_wordverifica si\wcon soporte Unicode encuentra resultados comoµAh - Solo
rgygit greppodían activar o desactivar Unicode;ag,pt,siftyucgusan\wsolo para ASCII git greppagó un costo grande de rendimiento al activar soporte Unicode, mientras queripgrepcasi no tuvo degradaciónripgrepincorpora la decodificación UTF-8 en la máquina de estados finitos y hace match directamente sobre cadenas de bytes UTF-8, sin una etapa separada de decodificación
Diferencias según la complejidad de la expresión regular
- En regex con sufijo literal como
[A-Z]+_RESUME,rgyucgusan_RESUMEpara encontrar rápidamente candidatos - En alternation de literales como
ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT,ripgrepusa Teddy y puede incluso evitar por completo el motor principal de regex - Incluso en alternation case-insensitive,
ripgrepcrea prefijos con combinaciones de mayúsculas y minúsculas para encontrar candidatos con Teddy, y valida solo esos candidatos con la regex completa - En la búsqueda
\p{Greek}, solo Rust regex y Go regex soportaban esa propiedad Unicode, yrgfue mucho más rápido queptysift - En la búsqueda case-insensitive de
\p{Greek},siftno pudo reportar matches yptno manejó correctamente mayúsculas y minúsculas Unicode - En patrones sin literales, como
\w{5}\s+..., el rendimiento del motor de regex se ve directamentergsiguió siendo rápido incluso con soporte Unicode activadogit greppaga un costo grande con soporte Unicode- Un DFA Unicode maneja un conjunto de estados NFA mucho mayor que un DFA ASCII; en el ejemplo, unas 250 NFA para ASCII frente a unas 77,000 para Unicode
Búsqueda en un solo archivo grande
- El benchmark de archivo único usó una muestra de OpenSubtitles2016
- la muestra en inglés es de aproximadamente 1 GB
- la muestra en ruso es de aproximadamente 1.6 GB
- En esta área, el rendimiento del motor de regex y las optimizaciones para literales se vuelven más importantes
- En
subtitles_literal, tanto la búsqueda deSherlock Holmescomo la deШерлок Холмсfueron más rápidas conrg ripgrepintenta elegir un byte poco frecuente en un literal para usarlo conmemchr- Una implementación estándar de Boyer-Moore suele usar el último byte para buscar candidatos
rgelige un byte más raro para poder saltar más tiempo dentro del loop optimizado con SIMD
- En UTF-8, muchos caracteres del patrón en ruso empiezan con
\xD0o\xD1, así que buscar el primer byte puede ser ineficiente rgusa una tabla precalculada de frecuencias de 256 bytes para preferir bytes menos frecuentes en lugar de\xD0o\xD1- En un solo archivo grande, como solo hay que crear el memory map una vez, la búsqueda con memory map de
rgfue alrededor de 25% más rápida querg (no mmap)
Unicode y alternation en archivo único
- En
subtitles_literal_casei,rgmaneja correctamente la búsqueda Unicode sin distinguir mayúsculas y minúsculas y aun así es rápido - GNU grep paga un costo grande en la búsqueda Unicode case-insensitive
- En la búsqueda case-insensitive en ruso,
grep (ASCII)parece ignorar en la práctica-i, yagreportó 0 matches - En
subtitles_alternate, la búsqueda con alternation de varios nombres de personajes fue más rápida conrgtanto en inglés como en ruso - En alternation en inglés,
rgfue aproximadamente un orden de magnitud más rápido que GNU grep - En
subtitles_alternate_casei,rgfue mucho más lento que antes, pero en inglés siguió superando a las otras herramientas - En este caso, había demasiados candidatos literales para que Teddy los manejara, así que
rgcambia de Teddy a Aho-Corasick ripgrepusa un Aho-Corasick “advanced” basado en tablas de transición, que realiza una transición por cada byte de entrada
Inner literal y patrones sin literales
- Los patrones como
\w+\s+Holmes\s+\w+estaban diseñados para evitar la optimización de literales de prefijo y sufijo, pero aun así podían aprovechar el literal internoHolmes ripgrepy GNU grep realizan optimización de inner literalripgrepusaregex-syntaxde Rust regex para extraer literales del AST del patrón- En la versión en ruso
\w+\s+Холмс\s+\w+, solo las herramientas con soporte correcto de Unicode pudieron dar resultados realmente útiles - En patrones largos sin ningún literal, como
\w{5}\s+...,rgestuvo entre los más rápidos en inglés, y la versión de GNU grep con soporte Unicode quedó fuera porque tardó más de 90 segundos en inglés y más de 4 minutos en ruso ripgrepmantiene el soporte Unicode y al mismo tiempo logra buen rendimiento al incorporar la decodificación UTF-8 dentro del DFA
Benchmarks adicionales
everythinges una prueba poco realista que hace match de todas las líneas con.*en el repositorio de Linuxrgreportó 22,065,361 líneas en 1.081 segundosagyptno reportaron todas las líneas, así que parece que tienen un límite de coincidencias
nothinges una prueba que no reporta ninguna línea al aplicar invert match sobre.*rgregistró 0.302 segundos ygit grep0.905 segundosptyucgno soportan búsqueda invertida
contextimprime 2 líneas de contexto alrededor deSherlock Holmesen el corpus de subtítulos en inglésrgfue similar asift, con 0.612 segundos frente a 0.717 segundosucgno soporta esa función
hugebuscaSherlock Holmesen los 9.3 GB completos de subtítulos en inglésrgmarcó 1.786 segundos, GNU grep 5.119 segundos ysift3.047 segundosucgdio un resultado incorrecto al reportar solo 1,543 líneas bajo la condición de conteo de líneas, y se sospecha que tuvo problemas al buscar en archivos de más de 2 GB
Conclusión
ripgrepno siempre ganó todos los benchmarks en búsquedas dentro del repositorio del kernel de Linux, pero era difícil decir que otra herramienta tuviera una ventaja clara tanto en rendimiento como en precisióngit greppodía llevar ventaja por unos pocos milisegundos en algunos casos simples, pero cuando el patrón se volvía más complejo o se requería Unicode, hubo casos en los queripgrepquedó muy por delante- Los siguientes factores contribuyen al rendimiento de
ripgrepen búsqueda de código- recorrido rápido de directorios, orientado a minimizar las llamadas a
stat - coincidencia de globs de
.gitignoreusandoRegexSet - distribución del trabajo mediante una cola Chase-Lev con work stealing
- la decisión de no usar memory maps al buscar entre muchos archivos pequeños
- un motor de expresiones regulares rápido
- recorrido rápido de directorios, orientado a minimizar las llamadas a
- En búsquedas sobre un solo archivo,
ripgrepfue el más rápido en todos los benchmarks principales o quedó muy por delante - En el rendimiento sobre un solo archivo influyen
memchrbasado en sparse bytes, Teddy SIMD, Aho-Corasick y un DFA con decodificación UTF-8 incorporada - En los benchmarks que requerían funciones Unicode, solo
rg, GNU grep ygit grepmostraron soporte realmente útil, y GNU grep ygit greppor lo general pagaron un costo de rendimiento alto - Los memory maps fueron desventajosos en Linux x86_64 para búsquedas paralelas entre muchos archivos pequeños, ventajosos para búsquedas en un solo archivo grande, y en entornos VM podían tener una penalización adicional
1 comentarios
Opiniones de Hacker News
Definitivamente es rápido, y sigo recomendando la combinación con fzf
Lo uso como una función de PowerShell que primero busca con
ripgrep, luego aplica búsqueda difusa sobre los archivos+texto resultantes, y muestra el contexto conbatEn proyectos donde se mezclan varios repositorios, permite acotar muy rápido cuando “sé que está en algún lado, pero no sé la ubicación exacta ni el nombre”
Este método viene de https://github.com/junegunn/fzf/blob/master/ADVANCED.md, y aunque no lo uses todo, vale la pena echarle un vistazo para sacar ideas
fzfPermite hacer búsqueda difusa no solo en archivos de texto, sino también en varios formatos de archivo como PDF y zip
Hay más detalles en https://github.com/phiresky/ripgrep-all/wiki/fzf-Integration
El enfoque consiste en elegir un resultado de
rgconfzf, parsear el archivo y el número de línea seleccionados, y abrirlo con$EDITOR +"${linenumber}" "$file"Es como moler café a mano en vez de usar un molinillo eléctrico
fzfpuedes elegir muchos archivos para agregarlos a Git y saltarte algunosSi agregas
fza = "!git ls-files -m -o --exclude-standard | fzf -m --print0 | xargs -0 git add"en[alias]degitconfig,git fzamuestra la lista de archivos modificados o aún no agregados, y puedes alternar elementos con espacio mientras avanzasEste alias y fzf+fd aceleran bastante parte del flujo de trabajo
También hay una guía que recopila cosas para poner en la configuración de zsh en macOS: https://gist.github.com/aclarknexient/0ffcb98aa262c585c49d4b...
ripgrepcasi de la misma formaLo uso como punto de partida para acotar archivos o proyectos en una base de código con cientos de repositorios, y luego profundizo más
En Emacs uso
ripgrepcon los paquetes project.el y dumb-jumpQuizá no sea la forma más popular, pero la experiencia completa es bastante satisfactoria
Basta con instalar
dumb-jumpconpackage-instally configurar(add-hook 'xref-backend-functions #'dumb-jump-xref-activate)En proyectos Python, al buscar la definición de un identificador con
M-.oC-u M-.,dumb-jumpejecuta un comandorgadecuado para el proyecto y el tipo de archivo actuales, y muestra los resultados en el buffer de XrefTambién soporta
ag, y si no estánagnirg, vuelve agrep, aunque al buscar en todo el directorio home puede ser lento, como era de esperarseripgrepcon bastante facilidadNo es estrictamente necesario un paquete externo; si quieres usarlo en lugar del lento
grepen directorios grandes, configura(setq xref-search-program 'ripgrep)Entonces una búsqueda de proyecto como
C-x p g foo RETse ejecuta en el proyecto actual con una forma comorg -i --null -nH --no-heading --no-messages -g '!*/' -e fooLos resultados aparecen en el buffer de Xref, lo que facilita moverse al siguiente/anterior match, saltar al código fuente y mostrarlo en una ventana dividida con teclas como
n,p,RET,C-oripgrep, aunque no ejecuté directamente esa expresión regular, creo que se puede quitar el flag --pcre2También parece que se pueden quitar la segunda y la tercera aserción
\b; la primera podría ser necesariaripgrepy también tiene bindings deevil-collection, así que se puede usar de forma satisfactoria: https://github.com/Wilfred/deadgrepEn esos casos, antes habría usado
rgrepLo interesante es que la búsqueda de VS Code ahora también funciona con
ripgrepa través de un wrapper de Node.jshttps://www.npmjs.com/package/@vscode/ripgrep
ripgrepPuedes encontrar el binario
rgdentro de la ruta de instalación de VS. Al menos en mi entorno laboral de Windows se podíaHe usado
ripgrepdurante unos 2 años y ya se volvió una herramienta imprescindibleLa razón principal por la que dejé
grepfue la facilidad de usoComo por defecto respeta las reglas de
.gitignorey omite archivos/directorios ocultos y archivos binarios,rg search_term directoryes mucho mejor que el comando equivalente congrep, y la mejora de velocidad viene de regaloCuando un match es demasiado largo y deja la terminal hecha un desastre, uso seguido la opción -M, como
-M 1000-Mes realmente excelenteEs especialmente cómoda para ignorar resultados de archivos minificados que no quieres ver, y también es buena la opción -g para buscar solo archivos con una extensión específica, como
-g *.csTambién es útil que sea un binario independiente y portable: cuando trabajo en una máquina nueva, pongo el ejecutable y configuro el alias de
greparg, así aunque escribagreppor costumbre, se ejecutargIncluso en 2023 puede seguir siendo cierto, pero el problema es que las herramientas paralelizadas que reemplazan a
grep, por ejemploripgrepoag, son tan rápidas frente algreptradicional que las pequeñas diferencias de velocidad entre ellas difícilmente sirven como criterio de diferenciación.Uso
agdentro de Emacs en una base de código de 900 mil líneas, y en un Ryzen Threadripper 2950X de 16 núcleos termina prácticamente al instante.No siento la necesidad de reducir algo de menos de 1 segundo a “un poco más de menos de 1 segundo”.
El atributo clave de las nuevas herramientas tipo
grepno es la velocidad; hay que evaluarlas y compararlas de otras maneras.agtiene caídas de rendimiento bastante grandes, y eso también se ve en el post del blog.Dicho eso, las cargas de trabajo varían según la persona, así que en algunos casos la diferencia de rendimiento puede no importar.
900 mil líneas no es tanto, y si la consulta es simple, la mayoría de las herramientas tipo
grepque no sean ingenuas la procesan muy rápido.Si miramos otros criterios de comparación,
agestá prácticamente en soporte vital, y parece que casi fue eliminado de Debian hasta que alguien lo rescató: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=999962El post del blog también compara el soporte Unicode, y
agprácticamente no tiene soporte Unicode. Quizá no sea importante para todo el mundo, pero basta como criterio de comparación no relacionado con el rendimiento.El tiempo de búsqueda toma lo que tarde el archivo en cargarse desde el disco, y las diferencias posteriores difícilmente son significativas.
Si los archivos están en caché, el tiempo de moverse por el sistema de archivos y escribir el comando domina más que el tiempo de búsqueda, así que de nuevo es difícil que la diferencia de rendimiento sea significativa.
El título necesita (2016).
Esto es el anuncio original, no información nueva.
“Ripgrep – A new command line search tool” https://news.ycombinator.com/item?id=12564442 (740 points | Sept 23, 2016 | 209 comments) — también hay discusión sobre velocidad.
“Ripgrep is faster (2016)” https://news.ycombinator.com/item?id=17941319 (98 points | Sept 8, 2018 | 40 comments)
No es más rápido que
qgrep.La forma en que funcionan ambos es bastante distinta, y aunque
qgrepse basa enre2, su velocidad viene de que tiene un índice.En repositorios grandes de archivos, tiene más sentido usar
qgrepcon un índice que recorrer todos los archivos cada vez; me pregunto por qué la gente olvida la opción deqgrep.Eso sí, si se necesita coincidencia multilínea en UTF-8,
ripgreptiene que recurrir a otra biblioteca PCRE2, así que no creo que sea tan rápido.ripgrep, es cierto queqgrep, al usar indexación, tiene ventaja frente a herramientas que no indexan.A cambio, hay que configurar y mantener el índice, así que la UX no es tan simple como “solo ejecutar la búsqueda”.
La razón por la que la gente no usa
qgrepes parecida a la razón por la que no usaripgrep: “para mí grep ya es suficientemente rápido”.En objetivos de búsqueda pequeños, muchas veces no se percibe la diferencia de velocidad entre
ripgrepygrep, o entreqgrepyripgrep.Si
ripgreptermina una búsqueda en el kernel de Linux en menos de 100 ms, que valga la pena pasar a una herramienta con indexación para un uso interactivo estándar depende del caso, pero por lo general no.He pensado en la idea de agregar indexación a
ripgrep: https://github.com/BurntSushi/ripgrep/issues/1497Además, la búsqueda multilínea no requiere PCRE2. El motor de expresiones regulares predeterminado también tiene soporte Unicode, y el soporte de búsqueda multilínea se mantiene incluso si se compila sin PCRE2.
Después de pasar de
ripgrepa ugrep, no he vuelto atrás.La velocidad es similar, pero tiene búsqueda difusa, una TUI útil para revisión de código y también puede buscar dentro de PDF y archivos comprimidos.
También es cómodo poder usar opcionalmente la sintaxis de búsqueda de Google.
https://ugrep.com
ripgrep, pero recientemente terminé buscandougreppor una función queripgrepno tiene: buscar dentro de archivos zip comprimidos.Permite buscar sin descomprimir en disco.
Trabajo con un corpus comprimido de millones de archivos de texto pequeños, y es bueno no tener que descomprimirlo todo al sistema de archivos. Algunos sistemas de archivos sufren a esa escala.
Aprecio ambas herramientas, y agradezco a sus respectivos autores.
grep, la mayoría de los resultados intenten venderme algo.ugrepyripgreppeleándose durante años en Reddit.Por ejemplo https://www.reddit.com/r/programming/comments/120wqvr/ripgre...
Me resulta un poco raro, considerando que solo se trata de herramientas open source.
fzf.Para mí parece difícil superar la configurabilidad y flexibilidad de
fzf.Creo que la función estrella es la compatibilidad con las opciones de línea de comandos de grep existentes.
Está bastante bien no tener que aprender un conjunto de opciones completamente nuevo.
Me pregunto por qué
grepno se reemplaza ni se mejoraCreo que este tema ya está algo viejo
Inercia, compatibilidad, resistencia al cambio, cosas como el dilema del innovador. No lo digo en sentido negativo; todo eso también aplica a mí
Sobre compatibilidad, se puede ver el FAQ: https://github.com/BurntSushi/ripgrep/blob/master/FAQ.md#pos...
Es cómoda, encaja bien con mi entorno de trabajo y no hay motivo para cambiarla y volver a ajustar todo
La analogía solo llega hasta el punto de que ya hay una silla como las de Razer cerca, y está sosteniendo ropa
xyz, debe aceptar estos argumentos y comportarse exactamente así”ripgrepSi la idea es reemplazar el comando
grepen sí por otra utilidad, parece que se romperían demasiadas cosas para el valor que se obtendríaQuien quiera un
grepmás rápido puede usar otra herramienta, y quien use elgrepexistente puede seguir usándolo; así que ya estamos cerca de un estado idealgrepes una herramienta de propósito general para encontrar texto en todo tipo de archivos, y está incrustada en el estándar UNIXAlgunos programadores la usan para buscar en código fuente, pero otras personas la usan en scripts o para búsquedas de texto que no tienen nada que ver con código fuente, y esperan que nunca crashee
En cambio,
ripgrepes una herramienta especializada y con opiniones fuertes, diseñada principalmente para buscar en repositorios de código fuenteNo hay mucho margen para hacer más rápida la búsqueda de texto de propósito general. Si se usa
mmap(), hay riesgo de crashear con archivos truncados; si se reduce la expresividad de las expresiones regulares, puede ser más rápida; y también se podría descartar el soporte para todos los locales y juegos de caracteres y hardcodear solo UTF-8/UTF-16, pero no se debería hacer esoBuscando en Portage, parece que también hay una versión que maneja otros documentos como PDF y doc
https://github.com/phiresky/ripgrep-all