5 puan yazan GN⁺ 2023-12-01 | 1 yorum | WhatsApp'ta paylaş
  • ripgrep (rg), The Silver Searcher tarzı kod arama kolaylığını GNU grep düzeyinde ham performansla birleştiren Rust tabanlı bir komut satırı arama aracıdır; Linux, Mac ve Windows ikililerini sunar
  • 25 benchmark’ta hem tek bir büyük dosyada hem de büyük dizinlerde aramada ripgrepten performans ve doğruluk açısından açıkça önde olan bir araç yoktu; Unicode desteğinin maliyeti de düşük tutuldu
  • .gitignore işleme, gizli ve ikili dosyaları varsayılan olarak hariç tutma, dosya türü filtreleri, isteğe bağlı PCRE2 desteği, birden çok kodlama ve sıkıştırılmış dosyada arama, ön işleme filtreleri gibi özelliklerle kod arama araçlarının pratik kullanım alanını genişletir
  • Linux çekirdek deposu ile OpenSubtitles2016 deneyleri arasındaki farklar büyük ölçüde literal optimizasyonu, Teddy SIMD çoklu desen araması, Aho-Corasick, UTF-8 çözümleme yöntemi, satır sayma ve .gitignore işleme maliyetine bağlıdır
  • Çok sayıda küçük dosyada paralel arama yaparken bellek eşleme yavaşlayabilir; tek bir büyük dosyada ise avantajlı olabilir. Bu nedenle ripgrep, duruma göre ara tamponla arama ile bellek eşlemeli aramayı ayrı ayrı kullanır

ripgrep’in hedeflediği konum

  • ripgrep, kod arama araçlarının kullanım kolaylığı ile grep türü araçların performansını birlikte hedefleyen bir komut satırı arama aracıdır
  • Karşılaştırılan araçlar GNU grep, git grep, The Silver Searcher (ag), Universal Code Grep (ucg), The Platinum Searcher (pt) ve sifttir
  • Benchmark’ların doğrulamaya çalıştığı üç ana nokta vardı
    • Hem tek dosyada hem de büyük dizinlerde aramada ripgrepten açıkça üstün bir araç yoktur
    • Unicode desteğini düzgün biçimde sunarken büyük bir performans maliyeti gerektirmez
    • Birden çok dosyada tek seferde arama yaparken bellek eşleme çoğunlukla daha hızlı değil, daha yavaş olabilir
  • Yazar, ripgrepin ve temelindeki düzenli ifade motorunun geliştiricisidir; benchmark’ların seçilmiş olup yanlılık taşıyabileceğini belirtir

Özellikler ve varsayılan davranış

  • ripgrepin çalıştırılabilir dosya adı rgdir
  • Varsayılan arama, geçerli dizini özyinelemeli olarak tarar, .gitignore kurallarına uyar ve gizli dosyalar ile ikili dosyaları atlar
  • .rgignore da desteklenir; .rgignore desenleri .gitignoredan önceliklidir
  • -u, -uu, -uuu ile ignore dosyalarını yok sayma, gizli dosyaları dahil etme ve ikili dosyaları dahil etme kapsamı genişletilebilir
    • rg -uuu, grep -a -r komutuna benzerdir
  • Dosya türü filtrelerini destekler
    • rg -tpy foo: yalnızca Python dosyalarında arar
    • rg -Tjs foo: JavaScript dosyalarını hariç tutar
    • --type-add ile yeni dosya türü kuralları eklenebilir
  • grepin birçok özelliğini de sunar
    • Bağlam çıktısı
    • Birden çok desenle arama
    • Renkli vurgulama
    • Tam Unicode desteği
  • Varsayılan düzenli ifade motoru look-around ve backreference desteklemez; ancak -P ile PCRE2 motoru seçilirse bu özellikler kullanılabilir
  • UTF-16’nın kısmi otomatik algılanmasını ve -E/--encoding tabanlı kodlama belirtmeyi de destekler
    • UTF-16, latin-1, GBK, EUC-JP, Shift_JIS vb. dahildir
  • -z/--search-zip ile gzip, xz, lzma, bzip2, lz4 gibi sıkıştırılmış dosyalarda aramayı destekler
  • PDF metni çıkarma, ek sıkıştırma açma, şifre çözme, otomatik kodlama algılama gibi isteğe bağlı ön işleme filtrelerini de destekler

Kullanmamak için nedenler

  • Taşınabilirlik ve her yerde kullanılabilirlik en yüksek öncelikse, standartlara uygun ve yaygın olarak kurulu olan grep uygundur
  • Başka araçlarda bulunan belirli bir özelliğe veya hataya bağımlıysanız ripgrep uygun olmayabilir
  • Bazı performans sınır durumlarında başka araçlar daha iyi çalışabilir
  • Kurulamıyorsa veya platform desteği yoksa kullanılamaz

grep türü araçların çalışma yapısı

  • Arama araçları genel olarak üç aşamadan geçer
    • Aranacak dosyaları toplama
    • Gerçek arama
    • Sonuçları yazdırma
  • grep türü araçlar büyük dosyaları iyi aramak zorunda olduğundan düzenli ifade motoru performansı önemlidir
  • ack türü araçların özyinelemeli dizin taramayı ve .gitignore gibi ignore kurallarını hızlı işlemesi gerekir
  • ripgrep iki yaklaşımı birleştirmeye çalışır
    • Hızlı düzenli ifade motoru
    • Paralel arama
    • Aranacak hedefleri filtreleme

Dosya toplama ve ignore işleme

  • ack türü araçlarda, geçerli dizinde hangi dosyaların aranacağını hızlı belirlemek önemlidir
  • Dizin dolaşma performansı, gereksiz stat çağrılarının sayısından etkilenir
  • ripgrep, en az sistem çağrısını hedefleyen özyinelemeli bir dizin yineleyicisi kullanır
  • .gitignore işlemenin bir maliyeti vardır
    • Her dizinde ignore dosyalarının bulunması gerekir
    • Ignore desenlerinin derlenmesi gerekir
    • Desenlerin tüm aday yollara uygulanması gerekir
  • Linux çekirdek deposunda 4.640 dizin ve 178 .gitignore dosyası vardı
  • ripgrep, .gitignore anlamını daha eksiksiz desteklemeye çalışır ve en son tanımlanan eşleşen desene öncelik verir
  • ucg, .gitignore yerine beyaz liste tabanlı glob kuralları kullandığı için hızlı olabilir; ancak bilinmeyen uzantılı dosyaları kaçırabilir

Düzenli ifade motoru farkları

  • Düzenli ifade motorları genel olarak iki sınıfa ayrılır
    • Backtracking tabanlı: özellik bakımından zengindir, ancak bazı girdilerde üstel zamanda yavaşlayabilir
    • Sonlu otomat tabanlı: özellikleri sınırlı olabilir, ancak aranan metnin uzunluğuna göre doğrusal zaman garantisi sağlar
  • Araçlara göre motorlar şöyledir
    • GNU grep, git grep: kendi sonlu otomat tabanlı motorları
    • ripgrep: Rust regex kütüphanesi, sonlu otomat tabanlı
    • ag, ucg: PCRE tabanlı backtracking
    • pt, sift: Go regex kütüphanesi, sonlu otomat tabanlı
  • ag ve ucg, PCRE kullandıkları için en kötü durumdaki backtracking davranışına maruz kalabilir
  • Örnek desen (a*)* c, PCRE tabanlı araçlarda sorun yaratabilir; diğer benchmark kapsamındaki araçlar ise bunu sorunsuz işler

Literal optimizasyonu ve SIMD

  • Basit dizge aramalarında literal arama optimizasyonu, düzenli ifade motorundan daha önemli hale gelebilir
  • Boyer-Moore klasik bir alt dizge arama algoritmasıdır ve aday konumları hızlı bulmak için memchr gibi rutinlerden yararlanabilir
  • memchr uygulamaları çoğu zaman SIMD komutlarıyla tek seferde 16 bayt denetler ve GB/sn düzeyinde iş hacmi sağlayabilir
  • Rust regex kütüphanesi, desenlerden prefix ve suffix literalleri agresif biçimde çıkarır
    • foo|bar
    • (a|b)c
    • [ab]foo[yz]
    • (foo)?bar
    • (foo)*bar
    • (foo){3,6}
  • Düzenli ifadenin tamamı tek bir literal veya literal alternation’a ayrıştırılabiliyorsa çekirdek düzenli ifade motoru hiç kullanılmayabilir
  • ripgrep, satır bazlı sonuç çıktısı özelliğinden yararlanarak inner literal de çıkarır
    • Örn. \w+foo\d+ içinde önce foo bulunur, ardından yalnızca aday satırlar düzenli ifadeyle doğrulanır
  • Birden çok literal aramasında GNU grep, Commentz-Walter benzeri bir algoritma kullanır; Rust regex ise Aho-Corasick veya Teddy SIMD algoritmasını kullanır
  • Teddy, Intel Hyperscan’den çıkan SIMD tabanlı bir çoklu desen arama algoritmasıdır ve ripgrepin GNU grep’i geçmesini sağlayan temel optimizasyonlardan biridir

Arama yöntemi: satır bazlı aramadan kaçınma

  • Saf bir uygulama dosyayı satır satır okur ve her satıra deseni uygular; ancak çoğu aramada eşleşmeler seyrek olduğu için bu verimsizdir
  • Arama araçları genellikle büyük bir bayt tamponunu tek seferde arar
    • Dosyayı bellek eşleme ile eşlemek
    • Dosyanın tamamını belleğe okumak
    • Sabit boyutlu bir ara tamponla kademeli arama
  • ripgrep, GNU grep ve git grep, kademeli aramayı destekler; bu sayede hem dosyalara hem de akışlara uygulanabilir
  • Kademeli aramanın uygulanması zordur
    • Satır numarası hesaplama
    • Tamponun satır ortasında bittiği durumları işleme
    • Uzun satırları işleme
    • Ters eşleşme işlemeyi yönetme
    • Eşleşme çevresindeki bağlam çıktısını işleme
  • ripgrep, uygulama karmaşıklığını göze alarak kademeli arama kullanır ve benchmark’larda çok sayıda küçük dosyada arama yaparken bellek eşlemeye göre daha hızlı sonuçlar gösterir

Çıktı ve paralellik

  • Paralel aramada her iş parçacığı doğrudan çıktı verirse farklı dosyalara ait sonuçlar birbirine karışabilir
  • Tüm paralel kod arama araçları arama sonuçlarını bellekteki ara tamponlara yazar ve yalnızca çıktı aşamasını seri hale getirir
  • Bu yöntem, arama iş parçacıklarının gerçek aramayı paralel olarak yapmasını sağlar
  • Dezavantajı, tüm satırların eşleştiği 2 GB’lık bir dosya gibi durumlarda bellek kullanımının artabilmesidir
  • ripgrep, stdin veya tek dosya aramalarında ara tampon olmadan doğrudan stdout’a yazar

Benchmark metodolojisi

  • Benchmark’lar son kullanıcı problemlerine göre ayrılır
    • Büyük ölçekli kod deposu araması
    • Tek büyük dosya araması
  • Arama desenleri basit literal’lere, alternation’a ve hafif düzenli ifadelere ağırlık verir
  • Araçların varsayılan davranışları farklı olduğundan, adil karşılaştırma için satır numarası, Unicode, .gitignore, beyaz liste gibi koşullar eşitlenmeye çalışılır
  • Benchmark’a alınan sürümler şunlardır
    • ripgrep v0.1.2
    • GNU grep v2.25
    • git grep v2.7.4
    • ag commit cda635, PCRE 8.38
    • ucg commit 487bfb, PCRE 10.21 JIT
    • pt commit 509368
    • sift commit 2d175c
  • ack, o dönemde diğer araçlardan çok daha yavaş olduğu için hariç tutuldu
  • Benchmark çalıştırıcısı, Python 3.5 veya üzerini gerektiren benchsuite’tir ve ripgrep deposuna dahildir
  • Her komut, ölçümden önce 3 kez warm-up çalıştırılarak derlemin OS page cache’e alınması sağlanır
  • Her komut 10 kez ölçülür; ortalama ve standart sapma kaydedilir
  • Çalıştırma ortamı Amazon EC2 c3.2xlarge, Ubuntu 16.04, Xeon E5-2680 2.8GHz, 16 GB bellek ve 80 GB SSD’dir
  • Yapılandırma günlükleri, özet sonuçlar ve ham CSV de yayımlanmıştır

Linux çekirdeği kod arama sonuçları

  • Kod arama benchmark’ı, derlenmiş Linux çekirdeği deposunun d0acc7 commit’i üzerinde çalıştırıldı
  • Derlenmiş çekirdek deposunun kullanılma nedeni, build çıktılarının depoda kalıp arama sonuçlarının ilgililiğini ve performansı etkileyebilmesidir
  • linux_literal_default içinde basit literal PM_RESUME araması, her aracın varsayılan davranışındaki farkları ortaya koyar
    • rg, .gitignore’a uyar ve gizli/binary dosyaları atlar
    • ag ve pt de benzerdir ancak satır sayısını sayar
    • ucg, .gitignore’ı okumaz ve beyaz liste temelli arama yapar
    • sift varsayılan olarak neredeyse her şeyi arar
    • git grep, aranacak dosya kümesini git index’inden alma avantajına sahiptir
  • .gitignore’a uymak sonuçların ilgililiğini artırır, ancak performans maliyeti doğurabilir
  • linux_literal içinde rg (whitelist), ucg ile neredeyse aynı performansı gösterdi; rg (ignore) ise git grep ile benzer seviyedeydi
  • rg (ignore) (mmap) ve ag (ignore) (mmap), bellek eşleme kullanımı nedeniyle yavaşladı; aynı koşullarda rg (ignore) çok daha hızlıydı
  • Yerel makinede de bellek eşleme sürümü daha yavaştı, ancak fark EC2’ye göre azaldı

Unicode ve büyük/küçük harf duyarsız arama

  • linux_literal_casei içinde pt, -i seçeneğini Go regexp’in (?i) biçimiyle işlediği için belirgin biçimde yavaşladı
  • sift, deseni ve arama bloğunu küçük harfe çevirme yöntemini kullandığı için daha az yavaşladı; ancak bu optimizasyon yalnızca ASCII büyük/küçük harflerini ele aldığından Unicode büyük/küçük harf işleme için doğru değildir
  • ripgrep, büyük/küçük harf duyarsız aramayı mümkün olan literal kombinasyonlarına dönüştürür ve Teddy ile aday konumları hızlıca bulur
  • linux_unicode_word içindeki \wAh araması, Unicode farkındalıklı \w’nin µAh gibi sonuçları yakalayıp yakalamadığını kontrol eder
  • Yalnızca rg ve git grep Unicode geçişini açıp kapatabiliyordu; ag, pt, sift ve ucg ASCII’ye özgü \w kullanıyordu
  • git grep, Unicode desteği açıldığında büyük performans maliyeti ödedi; ripgrep’te ise performans düşüşü neredeyse yoktu
  • ripgrep, UTF-8 çözümlemeyi sonlu durum makinesine dahil ederek ayrı bir çözümleme aşaması olmadan doğrudan UTF-8 bayt dizgileri üzerinde eşleştirme yapar

Düzenli ifade karmaşıklığına göre farklar

  • [A-Z]+_RESUME gibi literal suffix içeren düzenli ifadelerde rg ve ucg, _RESUME’ı kullanarak adayları hızlıca bulur
  • ERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVT gibi literal alternation’larda ripgrep Teddy kullanır ve çekirdek düzenli ifade motorunu hiç kullanmayabilir
  • Büyük/küçük harf duyarsız alternation’da da ripgrep, büyük/küçük harf kombinasyonu prefix’leri oluşturarak Teddy ile adayları bulur ve yalnızca adayları tam düzenli ifadeyle doğrular
  • \p{Greek} aramasında ilgili Unicode özelliğini yalnızca Rust regex ve Go regex destekliyordu; rg, pt ve sift’ten çok daha hızlıydı
  • \p{Greek} büyük/küçük harf duyarsız aramada sift eşleşme raporlayamadı; pt ise Unicode büyük/küçük harf işlemeyi doğru yapamadı
  • \w{5}\s+... gibi literal içermeyen desenlerde regex motorunun performansı doğrudan görünür hale gelir
    • rg, Unicode desteği açıkken bile hızlı sayılırdı
    • git grep, Unicode desteğinde büyük maliyet ödedi
    • Unicode DFA, ASCII DFA’dan çok daha büyük NFA durum kümeleriyle uğraşır; örnek değerler ASCII için yaklaşık 250, Unicode için yaklaşık 77.000 NFA durumudur

Tek büyük dosya araması

  • Tek dosya benchmark’ı OpenSubtitles2016 örneğini kullanır
    • İngilizce örnek yaklaşık 1 GB’tır
    • Rusça örnek yaklaşık 1,6 GB’tır
  • Bu alanda düzenli ifade motoru performansı ve literal optimizasyonu daha önemli hale gelir
  • subtitles_literal içinde Sherlock Holmes ve Шерлок Холмс aramalarında rg her ikisinde de en hızlıydı
  • ripgrep, literal’lerde seyrek bayt seçip bunu memchr içinde kullanmaya çalışır
    • Standart Boyer-Moore uygulaması genellikle son baytı aday aramada kullanır
    • rg, daha nadir bir bayt seçerek SIMD optimizasyonlu döngüde daha uzun atlamaya çalışır
  • Rusça desenlerde UTF-8’de birçok karakter \xD0 veya \xD1 ile başladığından ilk baytı aramak verimsiz olabilir
  • rg, önceden hesaplanmış 256 baytlık frekans tablosunu kullanarak \xD0, \xD1 yerine daha nadir baytları tercih eder
  • Tek büyük dosyada bellek eşlemesini yalnızca bir kez oluşturmak yeterli olduğundan rg’nin bellek eşlemeli araması, rg (no mmap)’ten yaklaşık %25 daha hızlıydı

Tek dosyada Unicode ve alternation

  • subtitles_literal_casei içinde rg, Unicode büyük/küçük harf duyarsız aramayı doğru işlerken hızlı kalır
  • GNU grep, Unicode büyük/küçük harf duyarsız aramada büyük maliyet öder
  • Rusça büyük/küçük harf duyarsız aramada grep (ASCII), -i seçeneğini fiilen yok sayıyor gibi görünür; ag ise 0 eşleşme raporlar
  • subtitles_alternate içinde birden fazla karakter adını içeren alternation aramasında rg, hem İngilizce hem Rusçada en hızlıydı
  • İngilizce alternation’da rg, GNU grep’ten yaklaşık bir büyüklük mertebesi daha hızlıydı
  • subtitles_alternate_casei içinde rg önceye göre çok daha yavaşladı, ancak İngilizcede diğer araçların önündeydi
  • Bu durumda Teddy’nin kaldırabileceğinden fazla literal adayı oluştuğu için rg, Teddy yerine Aho-Corasick’e geçer
  • ripgrep, transition table tabanlı “advanced” Aho-Corasick kullanarak her giriş baytı için tek bir geçiş yapar

İç literal ve literalsiz desenler

  • \w+\s+Holmes\s+\w+ gibi desenler prefix·suffix literal optimizasyonundan kaçınacak şekilde yapılandırılmış olsa da, içerideki Holmes literalinden yararlanabilir
  • ripgrep ve GNU grep inner literal optimizasyonu yapar
  • ripgrep, Rust regex’in regex-syntax bileşenini kullanarak desen AST’sinden literalleri çıkarır
  • Rusça sürüm \w+\s+Холмс\s+\w+ için yalnızca Unicode’u düzgün destekleyen araçlar anlamlı sonuç üretebildi
  • Hiç literal içermeyen uzun \w{5}\s+... deseninde rg, İngilizcede en hızlılar arasındaydı; GNU grep’in Unicode destekli sürümü İngilizcede 90 saniyeden fazla, Rusçada 4 dakikadan fazla sürdüğü için dışarıda bırakıldı
  • ripgrep, UTF-8 çözümlemeyi DFA’ya dahil ederek Unicode desteğini korurken performans da sağlar

Ek benchmark’lar

  • everything, Linux deposunda .* ile tüm satırları eşleştiren gerçekçi olmayan bir testtir
    • rg, 22.065.361 satırı 1,081 saniyede raporladı
    • ag ve pt tüm satırları raporlamadığından bir eşleşme sınırları var gibi görünüyor
  • nothing, .* üzerine invert match uygulayıp hiçbir satır raporlamayan bir testtir
    • rg 0,302 saniye, git grep 0,905 saniye kaydetti
    • pt ve ucg invert search desteklemiyor
  • context, İngilizce altyazı korpusunda Sherlock Holmes çevresindeki 2 satırlık bağlamı yazdırır
    • rg 0,612 saniye, sift 0,717 saniye ile benzerdi
    • ucg bu özelliği desteklemiyor
  • huge, 9,3 GB’lık İngilizce altyazı bütününde Sherlock Holmes arar
    • rg 1,786 saniye, GNU grep 5,119 saniye, sift 3,047 saniye kaydetti
    • ucg, satır sayma koşulunda yalnızca 1.543 satır raporlayarak yanlış sonuç üretti; 2 GB üstü dosya aramasında sorun yaşadığı düşünülüyor

Sonuç

  • ripgrep, Linux çekirdeği deposu aramalarında tüm benchmark’ları her zaman kazanmadı; ancak performans ve doğruluk açısından başka bir aracın açıkça üstün olduğu da söylenemedi
  • git grep, bazı basit örneklerde birkaç milisaniye öne geçebilse de, desen karmaşıklaştığında veya Unicode gerektiğinde ripgrep’in büyük farkla öne geçtiği durumlar oldu
  • ripgrep’in kod arama performansına şu etkenler katkı sağlıyor
    • Minimum stat çağrısını hedefleyen hızlı dizin dolaşımı
    • RegexSet kullanarak .gitignore glob eşleştirmesi
    • Chase-Lev work stealing queue ile iş dağıtımı
    • Çok sayıda küçük dosyada arama yaparken bellek eşlemesi kullanmama tercihi
    • Hızlı düzenli ifade motoru
  • Tek dosya aramalarında ripgrep, tüm ana benchmark’larda ya en hızlıydı ya da büyük farkla öndeydi
  • Tek dosya performansında sparse byte tabanlı memchr, Teddy SIMD, Aho-Corasick ve UTF-8 çözümlemeyi gömülü yapan DFA etkili olur
  • Unicode özelliği gerektiren benchmark’larda yalnızca rg, GNU grep ve git grep anlamlı destek gösterdi; GNU grep ve git grep ise genellikle yüksek performans maliyeti ödedi
  • Bellek eşlemesi, Linux x86_64 ölçütünde çok sayıda küçük dosyanın paralel aranmasında dezavantajlı, tek büyük dosya aramasında avantajlıydı; VM ortamında ek cezası olabilir

1 yorum

 
GN⁺ 2023-12-01
Hacker News yorumları
  • Kesinlikle hızlı ve fzf kombinasyonunu önermeye devam ediyorum
    Önce ripgrep ile bulup ardından sonuç dosyası+metin üzerinde fuzzy arama katmanı ekleyen ve bağlamı bat ile gösteren bir PowerShell fonksiyonu olarak kullanıyorum
    Birden fazla deponun karıştığı projelerde, “bir yerde olduğunu biliyorum ama tam konumunu ya da adını bilmiyorsam” çok hızlı şekilde daraltma yapabiliyorum
    Bu yöntem https://github.com/junegunn/fzf/blob/master/ADVANCED.md içinden geliyor; hepsini kullanmasanız bile fikir edinmek için göz atmaya değer

    • Bir adım daha ileri gidip ripgrep-all(rga) ile fzf entegrasyonunu öneririm
      Yalnızca metin dosyalarında değil, PDF ve zip gibi çeşitli dosya türlerinde de fuzzy arama yapabilirsiniz
      Ayrıntılar burada: https://github.com/phiresky/ripgrep-all/wiki/fzf-Integration
    • Bunu bash sürümü olarak da yazdım
      rg sonuçlarını fzf ile seçip, seçilen dosya ile satır numarasını parse ederek $EDITOR +"${linenumber}" "$file" ile açıyor
    • Vim'de fzf+rg yoksa neredeyse bozulmuş gibi hissediyorum
      Elektrikli değirmen yerine kahveyi elle öğütmek gibi
    • fzf ile Git'e eklenecek çok sayıda dosyayı seçip bazılarını atlayabiliyorsunuz
      gitconfig içindeki [alias] bölümüne fza = "!git ls-files -m -o --exclude-standard | fzf -m --print0 | xargs -0 git add" eklerseniz, git fza ile değiştirilmiş ya da henüz eklenmemiş dosyaların listesi gelir; boşluk tuşuyla öğeleri açıp kapatarak sonraki öğeye geçersiniz
      Bu takma ad ve fzf+fd, iş akışımın bazı kısımlarını epey hızlandırıyor
      macOS'ta zsh ayarına eklenecekleri derleyen bir rehber de var: https://gist.github.com/aclarknexient/0ffcb98aa262c585c49d4b...
    • Ben de ripgrepi neredeyse aynı şekilde kullanıyorum
      Yüzlerce deponun olduğu bir kod tabanında dosya ya da projeyi daraltmak için bir başlangıç noktası olarak kullanıyor, sonra daha derine iniyorum
  • Emacs'te ripgrepi project.el ve dumb-jump paketiyle kullanıyorum
    En popüler yöntem olmayabilir ama genel deneyim oldukça tatmin edici
    package-install ile dumb-jump kurup sadece (add-hook 'xref-backend-functions #'dumb-jump-xref-activate) ayarını yapmak yeterli
    Python projelerinde M-. veya C-u M-. ile tanımlayıcı tanımını aradığınızda, dumb-jump mevcut projeye ve dosya türüne göre rg komutunu çalıştırıp sonucu Xref buffer'ında gösteriyor
    ag de destekleniyor; ag ya da rg yoksa grepe geri düşüyor, ama home dizininin tamamında ararken beklendiği gibi yavaş olabilir

    • Emacs'in dahili project.el paketiyle bile ripgrepi oldukça kolay kullanabilirsiniz
      Harici paket şart değil; büyük dizinlerde yavaş grep yerine kullanmak için (setq xref-search-program 'ripgrep) ayarını yapmanız yeterli
      Böylece C-x p g foo RET gibi proje aramaları mevcut projede rg -i --null -nH --no-heading --no-messages -g '!*/' -e foo biçiminde çalışır
      Sonuçlar Xref buffer'ında görünür; n, p, RET, C-o gibi tuşlarla sonraki/önceki eşleşmeye gitmek, kaynağa atlamak ve bölünmüş pencerede göstermek rahattır
    • ripgrepin yazarı olarak baktığımda, o regex'i bizzat çalıştırmadım ama --pcre2 bayrağı olmadan da iş görecek gibi duruyor
      İkinci ve üçüncü \b assertion'larını da kaldırabilirsiniz; ilki gerekli olabilir
    • Deadgrep, ripgrep kullandığı ve evil-collection bağları da olduğu için memnuniyetle kullanılabilir: https://github.com/Wilfred/deadgrep
    • Bu yöntem de iyi ama birden fazla projede aynı anda arama yapmak ya da proje içindeki alt klasörlerde aramak istediğimde hâlâ rg.el kullanıyorum
      Böyle durumlarda normalde rgrep kullanmış olurdum
  • İlginç olan, VS Code aramasının da artık bir Node.js wrapper üzerinden ripgrep ile çalışıyor olması
    https://www.npmjs.com/package/@vscode/ripgrep

    • VS Code'u isteyebildiğiniz ya da kurabildiğiniz ama ripgrep kuramadığınız bir ortamdaysanız bu harika
      VS kurulum yolunun içinde rg binary'sini bulabilirsiniz. En azından benim işteki Windows ortamımda mümkündü
    • VS Code bir Electron uygulamasıyken aramanın neden bu kadar hızlı olduğunu hep merak ediyordum; şimdi sebebini biliyorum
    • Bu yeni bir özellik değil; VS Code'da 7 yıldır vardı
  • ripgrepi yaklaşık 2 yıldır kullanıyorum ve artık vazgeçilmez bir araç oldu
    grepten geçmemin ana nedeni kullanım kolaylığıydı
    Varsayılan olarak .gitignore kurallarına uyması, gizli dosya/dizinleri ve binary dosyaları atlaması sayesinde rg search_term directory, karşılık gelen grep komutundan çok daha iyi; hız artışı da bonus
    Eşleşme çok uzun olup terminali karmakarışık ettiğinde sık sık -M 1000 gibi -M seçeneğini kullanıyorum

    • -M gerçekten harika
      Özellikle görmek istemediğiniz minified dosya sonuçlarını yok saymak için çok kullanışlı; ayrıca -g *.cs gibi -g seçeneğiyle yalnızca belirli uzantılardaki dosyalarda arama yapmak da güzel
      Tek başına çalışabilen taşınabilir bir binary olması da faydalı; yeni bir makinede çalışırken çalıştırılabilir dosyayı koyup grep takma adını rg olarak ayarlarsanız, alışkanlıkla grep yazsanız bile aslında rg çalışır
  • Bu, 2023'te de hâlâ doğru olabilir; ancak sorun şu ki ripgrep veya ag gibi paralelleştirilmiş grep alternatifleri klasik grepten o kadar hızlı ki, aralarındaki küçük hız farklarını ayırt edici ölçüt olarak kullanmak zorlaşıyor.
    900 bin satırlık bir kod tabanında Emacs içinde ag kullanıyorum ve 16 çekirdekli Ryzen Threadripper 2950X üzerinde neredeyse anında bitiyor.
    1 saniyenin altını “biraz daha 1 saniyenin altına” indirgeme ihtiyacı hissetmiyorum.
    Yeni grep türü araçların temel niteliği hız değil; farklı açılardan değerlendirilip karşılaştırılmaları gerekiyor.

    • Bence 2016'da hız kesinlikle temel nitelikti.
      ag'de epey büyük bir performans uçurumu var ve bu blog yazısında da görülebiliyor.
      Yine de iş yükü kişiden kişiye değiştiği için, bazı durumlarda performans farkı önemli olmayabilir.
      900 bin satır çok büyük sayılmaz ve basit sorgular için naif olmayan çoğu grep türü araç bunu zaten çok hızlı işler.
      Başka karşılaştırma ölçütlerine bakarsak, ag neredeyse yaşam desteğinde; Debian'dan kaldırılmak üzereyken biri kurtarmış gibi görünüyor: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=999962
      Blog yazısı Unicode desteğini de karşılaştırıyor ve ag'nin pratikte Unicode desteği yok. Bu herkes için önemli olmayabilir ama performans dışı bir karşılaştırma ölçütü olarak fazlasıyla yeterli.
    • Benim deneyimimde bu araçların hepsi ciddi biçimde I/O darboğazına bağlı.
      Arama süresi, dosyaların diskten yüklenme süresi kadar sürüyor ve sonrasındaki farkların anlamlı olması zor.
      Dosyalar önbellekteyse, arama süresinden çok dosya sistemi içinde gezinmek ve komutu yazmak baskın hale geliyor; dolayısıyla burada da performans farklarının anlamlı olması güç.
  • Başlıkta (2016) olması gerekiyor.
    Bu, yeni bir bilgi değil; özgün gönderi.

  • qgrep'ten daha hızlı değil.
    İkisinin çalışma şekli oldukça farklı; qgrep re2 tabanlı olsa da hızını indeksten alıyor.
    Büyük dosya depolarında her seferinde tüm dosyaları taramak yerine qgrep ve bir indeks kullanmak daha mantıklı; insanların neden qgrep seçeneğini unuttuğunu merak ediyorum.
    Ama UTF-8'de çok satırlı eşleşme gerekiyorsa, ripgrep farklı bir PCRE2 kütüphanesine geçmek zorunda kaldığından o kadar hızlı olmadığını düşünüyorum.

    • ripgrep'in yazarı olarak, qgrep'in indeksleme kullandığı için indeksleme yapmayan araçlara göre avantajlı olduğu doğru.
      Bunun karşılığında indeksin kurulması ve korunması gerekiyor; yani UX, “sadece arat” kadar basit değil.
      İnsanların qgrep kullanmamasının sebebi, ripgrep kullanmamalarının “benim için grep zaten yeterince hızlı” gerekçesine benziyor.
      Küçük arama hedeflerinde çoğu zaman ripgrep ile grep veya qgrep ile ripgrep arasındaki hız farkı hissedilmiyor.
      Eğer ripgrep Linux çekirdeğinde bir aramayı 100 ms'nin altında bitiriyorsa, standart etkileşimli kullanımda bir indeksleme aracına geçmeye yetecek kadar rahatsızlık olup olmadığı duruma göre değişir, ama çoğu durumda yoktur.
      ripgrep'e indeksleme ekleme fikrini daha önce düşünmüştüm: https://github.com/BurntSushi/ripgrep/issues/1497
      Ayrıca çok satırlı arama PCRE2 gerektirmez. Varsayılan regex motoru da Unicode desteklidir ve PCRE2 olmadan derlendiğinde de çok satırlı arama desteği korunur.
  • ripgrep'ten ugrep'e geçtim ve bir daha geri bakmadım.
    Hızı benzer ama bulanık eşleştirme var, kod inceleme için işe yarar bir TUI'si var ve PDF ya da sıkıştırılmış dosyaların içinde de arama yapabiliyor.
    İsteğe bağlı olarak Google arama sözdizimi kullanılabilmesi de kullanışlı.
    https://ugrep.com

    • Ben büyük bir ripgrep hayranıyım ama yakın zamanda ripgrep'te olmayan bir özellik, yani zip arşivlerinin içinde arama, nedeniyle ugrep'i keşfettim.
      Diske çıkarmadan arama yapabiliyorsunuz.
      Milyonlarca küçük metin dosyasından oluşan sıkıştırılmış derlemelerle çalışıyorum; hepsini dosya sistemine açmak zorunda kalmamak çok iyi. Bazı dosya sistemleri bu ölçekte zorlanıyor.
      Her iki araca da minnettarım; ikisinin de yazarına teşekkürler.
    • grep içinde Google arama sözdizimini kullanmaya başlarsam sonuçların çoğunun bir şey satmaya çalışacağından korkuyorum.
    • Hafifçe “ugrep vs ripgrep” araması yaparken, ugrep ve ripgrep yazarlarının Reddit'te yıllar boyunca atıştığını düşündüren gönderiler gördüm.
      Örneğin https://www.reddit.com/r/programming/comments/120wqvr/ripgre...
      Sonuçta sadece açık kaynak araçlardan bahsediyoruz ama biraz tuhaf hissettiriyor.
    • TUI'nin sonuçları fzf'ye aktarmaktan daha iyi olup olmadığını merak ediyorum.
      Bana göre fzf'nin özelleştirilebilirliğini ve esnekliğini geçmek zor görünüyor.
    • Bunu paylaştığın için teşekkürler.
      Asıl killer feature'ın mevcut grep komut satırı seçenekleriyle uyumluluk gibi görünüyor.
      Baştan tamamen yeni bir seçenek kümesi öğrenmek zorunda olmamak oldukça güzel.
  • Neden grep'in değiştirilmediği ya da iyileştirilmediği merak ediliyor
    Bu konu da artık biraz eski görünmeye başladı

    • Açıklanabilecek pek çok neden var
      Atalet, uyumluluk, değişime direnç, yenilikçinin ikilemi gibi şeyler. Bunu olumsuz anlamda söylemiyorum; bunların hepsi benim için de geçerli
      Uyumluluk konusunda SSS'ye bakılabilir: https://github.com/BurntSushi/ripgrep/blob/master/FAQ.md#pos...
    • Şu an oturduğunuz 40 yıllık sandalyeyi Razer UltraSeat XR3000-A ile değiştirmemenize benziyor
      Rahat, etrafınızdaki çalışma ortamına iyi uyuyor ve durduk yere değiştirip her şeyi yeniden ayarlamak için bir neden yok
      Benzetme sadece, yakınlarda duran bir Razer sandalyeye kıyafet asılıyor olması noktasına kadar gidiyor
    • Unix'i tasarlayan biri, bazı sistem işlevlerini hem çekirdek OS işlevi hem de insanların kullandığı araçlar hâline getirdi ve bunun sonucunda onlarca yıl sonra “xyz adlı bir program mutlaka bulunmalı, bu argümanı almalı ve tam olarak şöyle davranmalı” gibi tuhaf bir sonuç ortaya çıktı
    • Zaten ripgrep gibi çeşitli alternatif araçlar kullanılabiliyor
      Eğer amaç grep komutunun kendisini başka bir yardımcı programla değiştirmekse, elde edilecek değere kıyasla bozulacak şey çok fazla gibi görünüyor
      Daha hızlı bir grep isteyenler başka araçlar kullanır, mevcut grep'i kullananlar da kullanmaya devam eder; yani zaten ideale yakın bir durum var
    • grep, her tür dosyada metin arayan genel amaçlı bir araç ve UNIX standardına gömülü
      Bazı programcılar bunu kaynak kod aramak için kullanıyor ama başkaları kaynak kodla ilgisiz metin aramalarında ya da betiklerde kullanıyor ve asla çökmemesini bekliyor
      Buna karşılık ripgrep, esas olarak kaynak kod depolarında arama yapmak için tasarlanmış, uzmanlaşmış ve belirgin tercihleri olan bir araç
      Genel amaçlı metin aramayı daha da hızlandırmak için çok fazla alan yok. mmap() kullanılırsa kesilmiş dosyalarda çökme riski olur, düzenli ifade ifade gücü azaltılırsa daha hızlı olabilir ve tüm locale ile karakter seti desteği bırakılıp yalnızca UTF-8/UTF-16 sabitlenebilir ama böyle yapılmamalı
  • Portage'da bakınca PDF ve doc gibi diğer belgeleri de işleyen bir sürüm var gibi görünüyor
    https://github.com/phiresky/ripgrep-all