Ripgrep: grep·ag·Git grep आदि से तेज़ सर्च टूल (2016)
(blog.burntsushi.net)- ripgrep(
rg) एक Rust-आधारित कमांड-लाइन सर्च टूल है, जो The Silver Searcher जैसी code search सुविधा को GNU grep-स्तर के raw performance के साथ जोड़ता है, और Linux·Mac·Windows binaries उपलब्ध कराता है - 25 benchmarks में, एकल बड़े file और बड़े directory search—दोनों में performance और accuracy के लिहाज़ से
ripgrepसे स्पष्ट रूप से आगे कोई टूल नहीं था, और Unicode support की लागत भी कम बनी रही .gitignoreप्रोसेसिंग, hidden·binary files को default रूप से बाहर रखना, file type filters, optional PCRE2 support, कई encodings और compressed files में search, और preprocessor filters तक शामिल करके यह code search tools के व्यावहारिक उपयोग-क्षेत्र को बढ़ाता है- Linux kernel repository और OpenSubtitles2016 experiments के बीच का अंतर मुख्य रूप से literal optimization, Teddy SIMD multi-pattern search, Aho-Corasick, UTF-8 decoding तरीका, line counting, और
.gitignoreप्रोसेसिंग लागत से प्रभावित होता है - कई छोटे files को parallel में search करते समय memory map धीमा पड़ सकता है, जबकि एकल बड़े file में यह फायदेमंद हो सकता है, इसलिए
ripgrepस्थिति के अनुसार intermediate buffer search और memory map search को अलग-अलग इस्तेमाल करता है
ripgrep ने अपना लक्ष्य कहाँ रखा
ripgrepएक कमांड-लाइन सर्च टूल है, जिसका लक्ष्य code search tools की सुविधा औरgrep-प्रकार के tools की performance—दोनों को साथ लाना है- तुलना के लिए
GNU grep,git grep,The Silver Searcher(ag),Universal Code Grep(ucg),The Platinum Searcher(pt),siftको लिया गया - benchmark जिन तीन मुख्य बातों की पुष्टि करना चाहता था, वे ये थीं
- single file और large directory search—दोनों में
ripgrepसे स्पष्ट रूप से बेहतर कोई tool नहीं है - सही Unicode support देने के लिए बड़े performance cost की ज़रूरत नहीं पड़ती
- कई files को एक साथ search करते समय memory map आम तौर पर तेज़ होने के बजाय धीमा भी पड़ सकता है
- single file और large directory search—दोनों में
- लेखक
ripgrepऔर उसके आधार regex engine—दोनों का निर्माता है, और यह भी बताता है कि benchmark चुने हुए होने के कारण पक्षपाती हो सकते हैं
फीचर्स और डिफ़ॉल्ट व्यवहार
ripgrepकी executable file का नामrgहै- default search current directory को recursively scan करता है,
.gitignoreका सम्मान करता है, और hidden files व binary files को skip करता है .rgignoreभी समर्थित है, और.rgignorepatterns को.gitignoreसे अधिक प्राथमिकता मिलती है-u,-uu,-uuuसे ignore files को नज़रअंदाज़ करना, hidden files शामिल करना, और binary files शामिल करना—इनकी सीमा बढ़ाई जा सकती हैrg -uuugrep -a -rके समान है
- file type filters समर्थित हैं
rg -tpy foo: केवल Python files में searchrg -Tjs foo: JavaScript files को छोड़कर search--type-addसे नए file type rules जोड़े जा सकते हैं
grepके कई features भी उपलब्ध हैं- context output
- multiple pattern search
- color highlight
- full Unicode support
- default regex engine look-around और backreference को support नहीं करता, लेकिन
-Pसे PCRE2 engine चुनने पर ये features इस्तेमाल किए जा सकते हैं - कुछ UTF-16 auto-detection और
-E/--encodingआधारित encoding specification भी supported है- इसमें UTF-16, latin-1, GBK, EUC-JP, Shift_JIS आदि शामिल हैं
-z/--search-zipके साथ gzip, xz, lzma, bzip2, lz4 जैसी compressed files में search supported है- PDF text extraction, अतिरिक्त decompression, decryption, और auto encoding detection जैसे arbitrary preprocessor filters भी supported हैं
इसे न इस्तेमाल करने के कारण
- अगर portability और हर जगह उपलब्ध होना सबसे पहली प्राथमिकता है, तो standard-अनुरूप और व्यापक रूप से installed grep अधिक उपयुक्त है
- अगर आप किसी दूसरे tool के specific feature या bug पर निर्भर हैं, तो
ripgrepउपयुक्त नहीं हो सकता - कुछ performance edge cases में दूसरे tools बेहतर काम कर सकते हैं
- अगर install नहीं किया जा सकता या platform support नहीं है, तो इसका उपयोग भी नहीं हो सकेगा
grep-प्रकार के tools की कार्य संरचना
- search tools मोटे तौर पर तीन चरणों से गुजरते हैं
- search के लिए files इकट्ठा करना
- actual search करना
- results output करना
grep-प्रकार के tools को बड़े files में अच्छी search करनी होती है, इसलिए regex engine performance महत्वपूर्ण हैack-प्रकार के tools को recursive directory traversal और.gitignoreजैसे ignore rules के application को तेज़ी से संभालना होता हैripgrepइन दोनों approaches को जोड़ने की कोशिश करता है- तेज़ regex engine
- parallel search
- search target filtering
file collection और ignore प्रोसेसिंग
ack-प्रकार के tools में current directory से किन files में search करनी है, यह जल्दी तय करना महत्वपूर्ण होता है- directory traversal performance अनावश्यक
statcalls की संख्या से प्रभावित होती है ripgrepminimal system calls का लक्ष्य रखने वाले recursive directory iterator का उपयोग करता है.gitignoreप्रोसेसिंग की लागत होती है- हर directory में ignore file ढूँढनी पड़ती है
- ignore patterns को compile करना पड़ता है
- सभी candidate paths पर patterns लागू करने पड़ते हैं
- Linux kernel repository में 4,640 directories और 178
.gitignorefiles थीं ripgrep.gitignoresemantics को अधिक पूर्ण रूप से support करने की कोशिश करता है, और सबसे हाल में defined matching pattern को प्राथमिकता देता हैucg.gitignoreकी जगह whitelist-आधारित glob rules इस्तेमाल करता है, इसलिए तेज़ हो सकता है, लेकिन unknown extension वाले files छूट सकते हैं
regex engine का अंतर
- regex engines को मोटे तौर पर दो श्रेणियों में बाँटा जा सकता है
- backtracking-आधारित: feature-rich, लेकिन कुछ inputs पर exponential time तक धीमे हो सकते हैं
- finite automata-आधारित: features सीमित हो सकते हैं, लेकिन search text की लंबाई के सापेक्ष linear time guarantee देते हैं
- हर tool के engine इस प्रकार हैं
- GNU grep,
git grep: अपना finite automata-आधारित engine ripgrep: Rust regex library, finite automata-आधारितag,ucg: PCRE-आधारित backtrackingpt,sift: Go regex library, finite automata-आधारित
- GNU grep,
agऔरucg, PCRE के उपयोग के कारण worst-case backtracking व्यवहार के प्रति अधिक exposed हो सकते हैं- उदाहरण pattern
(a*)* cPCRE-आधारित tools में समस्या पैदा कर सकता है, जबकि benchmark के अन्य tools इसे बिना समस्या के संभाल लेते हैं
literal optimization और SIMD
- simple string search में literal search optimization regex engine से भी अधिक महत्वपूर्ण हो सकता है
- Boyer-Moore एक classic substring search algorithm है, और candidate positions जल्दी खोजने के लिए
memchrजैसी routines का उपयोग कर सकता है memchrimplementations अक्सर SIMD instructions के ज़रिए एक बार में 16 bytes जाँचती हैं, और कई GB/s throughput दे सकती हैं- Rust regex library pattern से prefix·suffix literals को सक्रिय रूप से extract करती है
foo|bar(a|b)c[ab]foo[yz](foo)?bar(foo)*bar(foo){3,6}
- अगर पूरा regex एक single literal या literal alternation में टूट सकता है, तो core regex engine का उपयोग ही नहीं करना पड़ता
ripgrepline-based result output की विशेषता का उपयोग करके inner literal भी extract करता है- उदाहरण:
\w+foo\d+में पहलेfooढूँढकर केवल candidate lines को regex से verify किया जाता है
- उदाहरण:
- multiple literal search के लिए GNU grep, Commentz-Walter-जैसा algorithm इस्तेमाल करता है, जबकि Rust regex Aho-Corasick या Teddy SIMD algorithm इस्तेमाल करता है
- Teddy Intel Hyperscan से आया SIMD-आधारित multi-pattern search algorithm है, और
ripgrepके GNU grep से आगे निकलने वाली प्रमुख optimizations में से एक है
search तरीका: line-by-line search से बचना
- एक साधारण implementation file को line-by-line पढ़कर हर line पर pattern लागू करता है, लेकिन अधिकांश searches में match दुर्लभ होते हैं, इसलिए यह अप्रभावी है
- search tools आम तौर पर बड़े byte buffer को एक साथ search करते हैं
- file को memory map करना
- पूरी file को memory में पढ़ना
- fixed-size intermediate buffer के साथ incremental search
ripgrep, GNU grep,git grepincremental search को support करते हैं, इसलिए इसे files और streams—दोनों पर लागू किया जा सकता है- incremental search को implement करना कठिन है
- line number की गणना
- buffer का line के बीच में समाप्त होना
- लंबी lines को संभालना
- invert match को संभालना
- match के आसपास context output को संभालना
ripgrepimplementation complexity स्वीकार करके incremental search का उपयोग करता है, और benchmark में कई छोटे files की search में memory map की तुलना में तेज़ परिणाम दिखाता है
आउटपुट और parallelism
- parallel सर्च में अगर हर thread तुरंत आउटपुट लिखे, तो अलग-अलग फ़ाइलों के नतीजे आपस में मिल सकते हैं
- सभी parallel code search tools सर्च रिज़ल्ट को memory के intermediate buffer में लिखते हैं, और केवल output stage को serialize करते हैं
- यह तरीका search threads को वास्तविक सर्च parallel में करने देता है
- कमी यह है कि अगर 2GB की ऐसी फ़ाइल हो जिसमें हर लाइन match करती हो, तो memory usage बहुत बढ़ सकता है
ripgrepstdinया single file search में intermediate buffer के बिना सीधेstdoutमें लिखता है
benchmark methodology
- benchmark को end user की समस्याओं के आधार पर बाँटा गया है
- बड़े code repository में सर्च
- एकल बड़ी फ़ाइल में सर्च
- search patterns simple literals, alternation, और हल्के regular expressions की तरफ झुके हुए हैं
- हर tool का default behavior अलग है, इसलिए fair comparison के लिए line number, Unicode,
.gitignore, whitelist जैसी शर्तों को मिलाने की कोशिश की गई - benchmark के लिए इस्तेमाल किए गए version इस प्रकार हैं
ripgrepv0.1.2- GNU grep v2.25
git grepv2.7.4agcommitcda635, PCRE 8.38ucgcommit487bfb, PCRE 10.21 JITptcommit509368siftcommit2d175c
ackउस समय दूसरे tools की तुलना में बहुत धीमा था, इसलिए उसे शामिल नहीं किया गया- benchmark runner
benchsuiteहै, जिसे Python 3.5 या उससे ऊपर चाहिए, और यहripgreprepository में शामिल है - हर command को measurement से पहले 3 बार warm-up चलाया गया ताकि corpus OS page cache में लोड हो जाए
- हर command को 10 बार मापा गया और average तथा standard deviation दर्ज किए गए
- execution environment Amazon EC2
c3.2xlarge, Ubuntu 16.04, Xeon E5-2680 2.8GHz, memory 16GB, और 80GB SSD था - config log, summary results, और raw CSV भी सार्वजनिक किए गए
Linux kernel code search results
- code search benchmark built Linux kernel repository commit
d0acc7पर चलाया गया - built kernel repository का उपयोग इसलिए किया गया क्योंकि build artifacts repository में रह सकते हैं और search results की relevance तथा performance को प्रभावित कर सकते हैं
linux_literal_defaultमें simple literalPM_RESUMEकी खोज हर tool के default behavior का अंतर दिखाती हैrg.gitignoreका सम्मान करता है और hidden तथा binary files को छोड़ देता हैagऔरptभी मिलते-जुलते हैं, लेकिन वे lines की गिनती करते हैंucg.gitignoreनहीं पढ़ता और whitelist-आधारित खोज करता हैsiftdefault रूप से लगभग सब कुछ खोजता हैgit grepको git index से search file set पाने का फायदा मिलता है
.gitignoreका सम्मान करने से results की relevance बढ़ती है, लेकिन performance पर इसकी लागत हो सकती हैlinux_literalमेंrg (whitelist)नेucgके लगभग बराबर performance दिखाई, औरrg (ignore)का स्तरgit grepजैसा थाrg (ignore) (mmap)औरag (ignore) (mmap)memory map के उपयोग से धीमे हो गए, और समान शर्तों मेंrg (ignore)कहीं ज़्यादा तेज़ था- local machine पर भी memory-mapped versions धीमे थे, लेकिन EC2 की तुलना में अंतर कम था
Unicode और case search
linux_literal_caseiमेंptने-iको Go regexp के(?i)के रूप में संभाला, जिससे वह काफ़ी धीमा हो गयाsiftने pattern और search block को lowercase में बदलने का तरीका अपनाया, इसलिए वह कम धीमा हुआ, लेकिन यह optimization केवल ASCII case को संभालती है और Unicode case handling में सटीक नहीं हैripgrepcase-insensitive search को जहाँ संभव हो literal combinations में बदलता है, और Teddy से candidate positions को तेज़ी से ढूँढता हैlinux_unicode_wordमें\wAhखोज यह जाँचती है कि Unicode-aware\wक्याµAhजैसे results पकड़ता है- केवल
rgऔरgit grepमें Unicode toggle किया जा सकता था;ag,pt,sift,ucgASCII-only\wका उपयोग करते हैं git grepमें Unicode support चालू करने पर performance की बड़ी कीमत चुकानी पड़ी, लेकिनripgrepमें performance drop लगभग नहीं थाripgrepUTF-8 decoding को finite state machine में शामिल करता है, इसलिए अलग decoding step के बिना सीधे UTF-8 byte strings पर match करता है
regex complexity के अनुसार अंतर
[A-Z]+_RESUMEजैसे regex, जिनमें literal suffix हो, उनमेंrgऔरucg_RESUMEका उपयोग करके candidates जल्दी ढूँढते हैंERR_SYS|PME_TURN_OFF|LINK_REQ_RST|CFG_BME_EVTजैसी literal alternation मेंripgrepTeddy का उपयोग करता है और संभव है कि core regex engine का उपयोग ही न करे- case-insensitive alternation में भी
ripgrepcase combinations का prefix बनाकर Teddy से candidates ढूँढता है, और केवल candidates को पूरे regex से verify करता है \p{Greek}खोज में केवल Rust regex और Go regex उस Unicode property को support करते थे, औरrg,ptतथाsiftसे बहुत तेज़ था\p{Greek}की case-insensitive search मेंsiftmatch report नहीं कर पाया, औरptUnicode case handling सही तरीके से नहीं कर पाया\w{5}\s+...जैसे patterns, जिनमें literal नहीं है, उनमें regex engine की performance सीधे सामने आती हैrgUnicode support के साथ भी तेज़ बना रहाgit grepUnicode support पर बड़ी performance cost देता है- Unicode DFA को ASCII DFA की तुलना में बहुत बड़े NFA state sets संभालने पड़ते हैं; उदाहरण के तौर पर ASCII में लगभग 250, जबकि Unicode में लगभग 77,000 NFA states थे
एकल बड़ी फ़ाइल में खोज
- single file benchmark में OpenSubtitles2016 sample का उपयोग किया गया
- English sample लगभग 1GB था
- Russian sample लगभग 1.6GB था
- इस क्षेत्र में regex engine performance और literal optimization अधिक महत्वपूर्ण हो जाते हैं
subtitles_literalमेंSherlock HolmesऔरШерлок Холмсदोनों खोजों मेंrgसबसे तेज़ थाripgrepliterals में sparse bytes चुनकर उन्हेंmemchrमें इस्तेमाल करने की कोशिश करता है- standard Boyer-Moore implementation आमतौर पर candidate search के लिए आख़िरी byte का उपयोग करती है
rgज़्यादा दुर्लभ byte चुनता है ताकि SIMD-optimized loop में अधिक दूर तक skip किया जा सके
- Russian patterns में UTF-8 के तहत कई characters
\xD0या\xD1से शुरू होते हैं, इसलिए first-byte search अप्रभावी हो सकती है rgपहले से गणना की गई 256-byte frequency table का उपयोग करके\xD0,\xD1की जगह अधिक दुर्लभ bytes को प्राथमिकता देता है- single large file में memory map केवल एक बार बनानी पड़ती है, इसलिए
rgकी memory-mapped searchrg (no mmap)से लगभग 25% तेज़ थी
एकल फ़ाइल में Unicode और alternation
subtitles_literal_caseiमेंrgUnicode case-insensitive search को सही ढंग से संभालते हुए भी तेज़ है- GNU grep Unicode case-insensitive search में बड़ी performance cost देता है
- Russian case-insensitive search में
grep (ASCII)का-iव्यवहारिक रूप से अनदेखा करता हुआ दिखा, औरagने 0 matches report किए subtitles_alternateमें कई पात्रों के नामों वाली alternation search मेंrgEnglish और Russian दोनों में सबसे तेज़ था- English alternation में
rgGNU grep से लगभग एक अंक के गुणक जितना तेज़ था subtitles_alternate_caseiमेंrgपहले की तुलना में काफ़ी धीमा हुआ, लेकिन English में फिर भी दूसरे tools से आगे रहा- इस स्थिति में Teddy के लिए literal candidates बहुत ज़्यादा हो गए, इसलिए
rgTeddy की जगह Aho-Corasick पर स्विच करता है ripgreptransition table-आधारित “advanced” Aho-Corasick का उपयोग करता है, जो input के हर byte पर एक transition करता है
inner literal और बिना literal वाले pattern
\w+\s+Holmes\s+\w+जैसे pattern इस तरह बनाए गए थे कि prefix·suffix literal optimization से बचा जा सके, लेकिन inner literalHolmesका उपयोग किया जा सकता थाripgrepऔर GNU grep inner literal optimization करते हैंripgreppattern AST से literal निकालने के लिए Rust regex केregex-syntaxका उपयोग करता है- रूसी संस्करण
\w+\s+Холмс\s+\w+में केवल Unicode को सही तरह support करने वाले tools ही सार्थक परिणाम दे सके - बिल्कुल literal के बिना लंबे
\w{5}\s+...pattern मेंrgअंग्रेज़ी में सबसे तेज़ tools में था, और GNU grep का Unicode support वाला version अंग्रेज़ी में 90 सेकंड से ज़्यादा, रूसी में 4 मिनट से ज़्यादा लेने के कारण बाहर कर दिया गया ripgrepUTF-8 decoding को DFA में शामिल करने के तरीके से Unicode support बनाए रखते हुए performance हासिल करता है
अतिरिक्त benchmark
everythingLinux repository में.*से हर line को match कराने वाला अवास्तविक test हैrgने 22,065,361 lines को 1.081 सेकंड में report कियाagऔरptने सभी lines report नहीं कीं, इसलिए लगता है कि उनमें match limit है
nothing.*पर invert match लागू करके कोई भी line report न करने वाला test हैrgने 0.302 सेकंड औरgit grepने 0.905 सेकंड दर्ज किएptऔरucginvert search support नहीं करते
contextअंग्रेज़ी subtitle corpus मेंSherlock Holmesके आसपास की 2 lines का context output करता हैrg0.612 सेकंड औरsift0.717 सेकंड के साथ लगभग समान थेucgयह feature support नहीं करता
huge9.3GB की पूरी अंग्रेज़ी subtitle file मेंSherlock Holmesखोजता हैrgने 1.786 सेकंड, GNU grep ने 5.119 सेकंड, औरsiftने 3.047 सेकंड दर्ज किएucgने line counting condition में केवल 1,543 lines report कीं, इसलिए उसने गलत परिणाम दिया, और शक है कि 2GB से बड़ी files खोजने में समस्या हुई
निष्कर्ष
- Linux kernel repository search में
ripgrepहर benchmark में हमेशा नहीं जीता, लेकिन performance और accuracy में यह कहना मुश्किल था कि कोई दूसरा tool स्पष्ट रूप से बेहतर है git grepकुछ सरल मामलों में कुछ millisecond आगे हो सकता था, लेकिन pattern जटिल होने पर या Unicode की ज़रूरत पड़ने परripgrepकई बार बहुत आगे निकल गयाripgrepकी code search performance में निम्न तत्वों का योगदान है- न्यूनतम
statcalls को लक्ष्य बनाने वाली तेज़ directory traversal .gitignoreglob matching के लिएRegexSetका उपयोग- Chase-Lev work stealing queue के ज़रिए काम का वितरण
- कई छोटी files खोजते समय memory map का उपयोग न करने का निर्णय
- तेज़ regular expression engine
- न्यूनतम
- single file search में
ripgrepसभी प्रमुख benchmarks में सबसे तेज़ था या बड़े अंतर से आगे था - single file performance पर sparse byte-आधारित
memchr, Teddy SIMD, Aho-Corasick, और UTF-8 decoding built-in DFA का प्रभाव पड़ता है - Unicode feature की ज़रूरत वाले benchmarks में केवल
rg, GNU grep, औरgit grepने सार्थक support दिखाया, और GNU grep तथाgit grepने आम तौर पर इसके लिए बड़ा performance cost चुकाया - memory map Linux x86_64 के आधार पर कई छोटी files की parallel search में नुकसानदेह था, single बड़ी file search में फायदेमंद था, और VM environment में अतिरिक्त penalty हो सकती है
1 टिप्पणियां
Hacker News की राय
यह वाकई तेज़ है, और मैं लगातार fzf combination की सिफारिश करता रहता हूँ
पहले
ripgrepसे खोजता हूँ, फिर मिले हुए file+text results पर fuzzy search लगाता हूँ, औरbatसे context दिखाने वाले PowerShell function के रूप में इस्तेमाल कर रहा हूँजिन projects में कई repositories मिली हुई हैं, वहाँ “मुझे पता है कि यह कहीं है, लेकिन सही location या नाम नहीं पता” वाली स्थिति में बहुत तेज़ी से scope घटाया जा सकता है
यह तरीका https://github.com/junegunn/fzf/blob/master/ADVANCED.md से आया है, और पूरा इस्तेमाल न भी करें तो ideas लेने के लिए एक बार देखना worth it है
fzfके साथ integrate करने की सिफारिश करूँगाइससे सिर्फ text files ही नहीं, PDF, zip जैसे कई file formats में भी fuzzy search किया जा सकता है
ज़्यादा जानकारी https://github.com/phiresky/ripgrep-all/wiki/fzf-Integration में है
इसमें
rgresults कोfzfसे चुनते हैं, चुनी हुई file और line number को parse करके$EDITOR +"${linenumber}" "$file"से open करते हैंजैसे electric grinder की जगह हाथ से coffee पीस रहे हों
fzfइस्तेमाल करने पर Git में add करने के लिए बहुत-सी files चुनते हुए कुछ को skip किया जा सकता हैgitconfigके[alias]मेंfza = "!git ls-files -m -o --exclude-standard | fzf -m --print0 | xargs -0 git add"डाल दें तोgit fzaसे modified या अभी तक add न हुई files की list दिखती है, और space से items toggle करते हुए आगे बढ़ते हैंयह alias और fzf+fd workflow के कुछ हिस्सों को काफी तेज़ बना देते हैं
macOS पर zsh settings में डालने वाली चीज़ों को समेटने वाली guide भी है: https://gist.github.com/aclarknexient/0ffcb98aa262c585c49d4b...
ripgrepको लगभग इसी तरीके से इस्तेमाल करता हूँसैकड़ों repositories वाले codebase में किसी file या project को narrow down करने के starting point के रूप में इस्तेमाल करता हूँ, फिर उसके बाद और अंदर जाता हूँ
Emacs में
ripgrepको project.el और dumb-jump packages के साथ इस्तेमाल कर रहा हूँयह सबसे popular तरीका नहीं हो सकता, लेकिन पूरा experience काफी संतोषजनक है
package-installसेdumb-jumpinstall करके सिर्फ(add-hook 'xref-backend-functions #'dumb-jump-xref-activate)set करना होता हैPython project में
M-.याC-u M-.से identifier definition खोजने परdumb-jumpcurrent project और file type के हिसाब सेrgcommand चलाता है और results को Xref buffer में दिखाता हैयह
agभी support करता है, और अगरagयाrgनहीं है तोgrepपर fallback करता है, लेकिन पूरे home directory में खोजते समय उम्मीद के मुताबिक धीमा हो सकता हैripgrepकाफी आसानी से इस्तेमाल किया जा सकता हैexternal package ज़रूरी नहीं है, और बड़ी directories में slow
grepकी जगह इस्तेमाल करना हो तो(setq xref-search-program 'ripgrep)set कर देंफिर
C-x p g foo RETजैसी project search current project मेंrg -i --null -nH --no-heading --no-messages -g '!*/' -e fooके रूप में चलेगीResults Xref buffer में दिखते हैं, इसलिए
n,p,RET,C-oजैसी keys से next/previous match पर जाना, source jump करना और split window में दिखाना सुविधाजनक हैripgrepके लेखक के नज़रिए से, वह regex मैंने सीधे run नहीं किया है, लेकिन लगता है --pcre2 flag हटाया जा सकता हैदूसरा और तीसरा
\bassertion भी शायद हटाया जा सकता है, और पहला ज़रूरी हो सकता हैripgrepइस्तेमाल करता है और इसमेंevil-collectionbindings भी हैं, इसलिए इसे आराम से इस्तेमाल किया जा सकता है: https://github.com/Wilfred/deadgrepऐसी situation में पहले मैं
rgrepइस्तेमाल करतादिलचस्प बात यह है कि VS Code search भी अब Node.js wrapper के जरिए
ripgrepपर चलता हैhttps://www.npmjs.com/package/@vscode/ripgrep
ripgrepinstall नहीं कर सकते, तो यह बहुत अच्छा हैVS install path के अंदर
rgbinary मिल सकती है। कम से कम मेरे Windows office environment में तो ऐसा संभव थामैं
ripgrepकरीब 2 साल से इस्तेमाल कर रहा हूँ और अब यह indispensable tool बन गया हैgrepसे switch करने की मुख्य वजह ease of use थीdefault रूप से यह
.gitignorerules का सम्मान करता है और hidden files/directories व binary files को skip करता है, इसलिएrg search_term directoryउसके equivalentgrepcommand से बहुत बेहतर है, और speed improvement bonus हैजब match बहुत लंबा हो और terminal अस्त-व्यस्त हो जाए, तब मैं अक्सर
-M 1000जैसे -M option का इस्तेमाल करता हूँ-Mसच में शानदार हैजिन minified file results को नहीं देखना चाहते उन्हें ignore करने में यह खास तौर पर convenient है, और
-g *.csजैसे -g option से सिर्फ किसी खास extension की files search करना भी अच्छा हैstandalone portable binary होना भी उपयोगी है; नई machine पर काम करते समय executable डालकर
grepalias कोrgपर set कर दें, तो आदत सेgreptype करने पर भीrgही चलेगा2023 में भी यह बात शायद अब भी सही हो सकती है, लेकिन समस्या यह है कि parallelized
grepalternative tools, जैसेripgrepयाag, पुरानेgrepसे इतने ज़्यादा तेज़ हैं कि इनके बीच की छोटी-छोटी speed differences को अलग पहचान का आधार बनाना मुश्किल हैमैं 9 लाख lines वाले codebase में Emacs के अंदर
agइस्तेमाल करता हूँ, और 16-core Ryzen Threadripper 2950X पर यह practically तुरंत खत्म हो जाता है1 सेकंड से कम को “थोड़ा और 1 सेकंड से कम” करने की ज़रूरत महसूस नहीं होती
नए
grep-type tools की मुख्य खासियत speed नहीं है; उनका मूल्यांकन और तुलना दूसरे तरीकों से करनी चाहिएagमें काफी बड़ा performance cliff है, और यह blog post में भी दिखता हैहालांकि workload हर व्यक्ति का अलग होता है, इसलिए कुछ मामलों में performance difference मायने नहीं रख सकता
9 लाख lines बहुत बड़ा नहीं है, और simple query हो तो naive न होने वाले ज़्यादातर
grep-type tools उसे बहुत जल्दी handle कर लेते हैंदूसरे comparison criteria से देखें तो
agलगभग life support पर है, और लगता है Debian से हटाए जाने वाला था लेकिन किसी ने उसे बचा लिया: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=999962blog post Unicode support की भी तुलना करता है, और
agमें practically Unicode support नहीं है। यह हर किसी के लिए अहम नहीं होगा, लेकिन non-performance comparison criterion के तौर पर पर्याप्त हैsearch time उतना ही लगता है जितना files को disk से load होने में लगता है, और उसके बाद का फर्क meaningful होना मुश्किल है
अगर files cache में हों, तो search time से ज़्यादा file system में navigate करने और command लिखने का time dominate करता है, इसलिए वहाँ भी performance difference meaningful होना मुश्किल है
title में (2016) होना चाहिए
यह असल में release announcement है, नई जानकारी नहीं
“Ripgrep – A new command line search tool” https://news.ycombinator.com/item?id=12564442 (740 points | Sept 23, 2016 | 209 comments) — speed से जुड़ी discussion भी है
“Ripgrep is faster (2016)” https://news.ycombinator.com/item?id=17941319 (98 points | Sept 8, 2018 | 40 comments)
qgrepसे तेज़ नहीं हैदोनों के काम करने का तरीका काफी अलग है, और
qgrepre2-based है लेकिन उसकी speed index होने की वजह से आती हैबड़े file repositories में हर बार सभी files scan करने के बजाय
qgrepऔर index इस्तेमाल करना ज़्यादा समझदारी लगता है, और मुझे हैरानी है कि लोगqgrepoption क्यों भूल जाते हैंहालांकि अगर UTF-8 में multi-line matching चाहिए, तो
ripgrepको किसी दूसरी PCRE2 library पर fallback करना पड़ता है, इसलिए मुझे नहीं लगता कि वह इतना तेज़ रहता हैripgrepके author के तौर पर, यह सही है किqgrepindexing इस्तेमाल करता है, इसलिए non-indexing tools की तुलना में उसे फायदा हैलेकिन index set up और maintain करना पड़ता है, इसलिए UX “बस search चलाओ” जितना simple नहीं रहता
लोग
qgrepक्यों नहीं इस्तेमाल करते, इसकी वजह वैसी ही है जैसे “मेरे लिए grep भी काफी तेज़ है” कहकर वेripgrepनहीं इस्तेमाल करतेछोटे search targets में अक्सर
ripgrepऔरgrep, याqgrepऔरripgrepके speed difference को महसूस नहीं किया जा सकताअगर
ripgrepLinux kernel search को 100ms के अंदर खत्म कर देता है, तो standard interactive use में indexing tool पर switch करने लायक तकलीफ़ होगी या नहीं, यह situation पर निर्भर है, लेकिन आम तौर पर नहीं होगीripgrepमें indexing जोड़ने का idea मैंने सोचा है: https://github.com/BurntSushi/ripgrep/issues/1497और multi-line search के लिए PCRE2 की ज़रूरत नहीं होती। default regex engine में भी Unicode support है, और PCRE2 के बिना build करने पर भी multi-line search support बना रहता है
ripgrepसे ugrep पर switch करने के बाद वापस देखने की ज़रूरत नहीं पड़ीspeed भी similar है, लेकिन इसमें fuzzy matching है, code review के लिए काम आने वाला TUI भी है, और PDF या compressed files के अंदर भी search कर सकता है
optional तौर पर Google search syntax इस्तेमाल कर पाना भी सुविधाजनक है
https://ugrep.com
ripgrepका बड़ा fan हूँ, लेकिन हाल मेंripgrepमें न होने वाले feature, यानी zip archive के अंदर search, की वजह से मुझेugrepदेखना पड़ाdisk पर unzip किए बिना search कर सकते हैं
मैं लाखों छोटे text files वाले compressed corpus के साथ काम करता हूँ, और अच्छा है कि अब पूरी चीज़ को file system पर extract करने की ज़रूरत नहीं। कुछ file systems इस scale पर struggle करते हैं
दोनों tools के लिए आभारी हूँ, और उनके respective authors को धन्यवाद
grepमें Google search syntax इस्तेमाल करना शुरू कर दूँ, तो डर है कि ज़्यादातर results कुछ बेचने की कोशिश करेंगेugrepऔरripgrepके authors Reddit पर कई सालों तक बहस करते रहेउदाहरण के लिए https://www.reddit.com/r/programming/comments/120wqvr/ripgre...
बात तो बस open source tools की है, लेकिन यह थोड़ा अजीब लगा
fzfमें pass करने से बेहतर है या नहींमेरे लिए
fzfकी configurability और flexibility को beat करना मुश्किल लगता हैkiller feature मौजूदा grep command-line options compatibility लगती है
बिल्कुल नया option set सीखने की ज़रूरत न होना काफी अच्छा है
यह सोचकर हैरानी होती है कि
grepको बदला या बेहतर क्यों नहीं किया गयायह विषय भी अब थोड़ा पुराना लगने लगा है
जड़ता, compatibility, बदलाव के प्रति प्रतिरोध, innovator's dilemma जैसी चीज़ें। यह मैं नकारात्मक अर्थ में नहीं कह रहा; ये सब मुझ पर भी लागू होती हैं
compatibility के बारे में FAQ देखें: https://github.com/BurntSushi/ripgrep/blob/master/FAQ.md#pos...
वह आरामदायक है, आसपास के कामकाजी माहौल में अच्छी तरह फिट है, और उसे बदलकर सब कुछ फिर से सेट करने की कोई खास वजह नहीं है
यह उपमा बस इस हद तक ही जाती है कि Razer जैसी कोई कुर्सी पास में पहले से है और उस पर कपड़े रखे हुए हैं
xyzनाम का program अनिवार्य रूप से होना चाहिए, और उसे यह argument लेकर ठीक इसी तरह behave करना चाहिए” जैसी अजीब स्थिति बन गईripgrepजैसे कई alternative tools पहले से इस्तेमाल किए जा सकते हैंअगर बात
grepcommand को ही किसी दूसरी utility से बदलने की है, तो मिलने वाले value की तुलना में टूटने वाली चीज़ें बहुत ज़्यादा दिखती हैंजिन्हें तेज़
grepचाहिए वे दूसरा tool इस्तेमाल करें, और जो मौजूदाgrepइस्तेमाल करते हैं वे उसे जारी रखें—इसलिए यह पहले से ही लगभग ideal स्थिति हैgrepहर तरह की files में text खोजने वाला general-purpose tool है, और UNIX standard में गहराई से शामिल हैकुछ programmers इसे source code search के लिए इस्तेमाल करते हैं, लेकिन दूसरे लोग इसे source code से असंबंधित text search या scripts में इस्तेमाल करते हैं, और उम्मीद करते हैं कि यह कभी crash न करे
इसके उलट
ripgrepमुख्य रूप से source code repositories में search के लिए डिज़ाइन किया गया specialized और opinionated tool हैgeneral-purpose text search को और तेज़ बनाने की गुंजाइश बहुत ज़्यादा नहीं है।
mmap()इस्तेमाल करने पर truncated files में crash का जोखिम होता है, regular expressions की expressiveness घटाने से यह तेज़ हो सकता है, और सभी locale और character set support छोड़कर सिर्फ UTF-8/UTF-16 को hardcode भी किया जा सकता है, लेकिन ऐसा नहीं करना चाहिएPortage में देखने पर लगता है कि PDF और doc जैसे दूसरे documents तक संभालने वाला version भी है
https://github.com/phiresky/ripgrep-all