Metin verisi işlemek ve aramak söz konusu olduğunda, düzenli ifadeler (regular expressions) ve bunları kullanmamızı sağlayan yazılımlar en sık başvurduğumuz şeylerden biridir. Yazılımla uğraşan, komut satırında bir şeyler yapan kişilerin grep
ya da benzeri bir araç kullanmadan yaşadıklarını düşünmek imkansızdır.
Bu yazdıklarımda herhangi bir yenilik yok elbette. Ben de doğal olarak onlarca yıldır severek kullanılan ve çok fayda sağlayan düzenli ifade teknolojisinde pek bir yenilik olmadığını düşünüyordum kısa bir süre öncesine dek. Ama yanılmışım!
Bu yazıda son zamanlarda hayatımıza giren iki yeni düzenli ifade aracından çok kısaca bahsedeceğim: ICgrep and ripgrep.
ICGrep, Kanada'daki Simon Fraser üniversitesinde Dr. Robert D. Cameron tarafından geliştirilen yeni ve paralel 'bitstream' teknolojisine dayanan bir düzenli ifade ve metin işleme aracı. Bu alanda pek çok kullanim şekli için en hızlı sistem olma iddiasını taşıyor. ICGrep'in MacOS / OS X icin calıstırılabilir halini http://www.icgrep.com/downloads.htm adresinden temin etmek mümkun. Diger isletim sistemleri için ise yine açık olarak erisilebilen kaynak kodundan kendiniz derleyebilirsiniz.
ripgrep ise Andrew Gallant ve diger yazılımcılar tarafindan Rust programlama dili kullanılarak GitHub uzerinden geliştirilen bir düzenli ifade aracı; kaynak kodu için adres: https://github.com/BurntSushi/ripgrep. Tıpkı ICGrep gibi, ripgrep de cok hızlı olma, tam Unicode destegi gibi özellikler sunduğunu belirtiyor. Buna ek olarak 'Silver Searcher (ag)' ve 'ack' gibi özellikleri bulunduğunu, yani özellikle Git ile calisan yazılımcıların kaynak kod dosyalarında bir şeyler ararken işleri kolaylastırdığını belirtmekte de fayda var.
Hiçbir bilimsellik iddiasi gütmeyen bu performans kıyaslamasında kullandıgım bilgisayarda icgrep
, ripgrep
, işletim sistemi ile birlikte kurulu gelen BSD grep
, GNU grep
ve ag
yi (Silver Searcher) kıyaslayacağım çok basitce.
Test ettigim ortamın özellikleri: OS X El Capitain Version 10.11.4, 2.8 GHz Intel Core i7, 16 GB 1600 MHz DDR3 RAM, ve 500 GB SSD.
Kullandıgım metin dosyası su adresten indirdiğim Arapça Wikipedia sayfaları (hepsini içeren tek bir dosya): https://dumps.wikimedia.org/arwiki/latest/arwiki-latest-pages-articles.xml.bz2 (tarih: 01-Oct-2016 19:56. Büyüklük: 510,252,224
byte (sıkıstırılmıs halde); 3,311,291,975
byte (açık halde) yani yaklasık 3.1 GB
). Her düzenli ifade komutunu 5 kere çalıştırıp ortalamaları not ettim.
Önce OS X ile gelen BSD grep
ile başlayalım:
$ /usr/bin/grep --version
grep (BSD grep) 2.5.1-FreeBSD
$ time /usr/bin/grep -c -i Wats.n arwiki-latest-pages-articles.xml
793
real 1m6.120s
user 1m5.550s
sys 0m0.530s
Elbette bu çok basit bir düzenli ifade ama unutmayın ki içinde arama yaptığımız metin dosyasının büyüklügü 3.1 GB. Bu işlem yaklasik 1 dakika sürdü. Elbette çok daha iyi bir performans saglamak mümkün.
GNU grep
i deneyelim:
$ /usr/local/bin/grep --version
grep (GNU grep) 2.26
$ time /usr/local/bin/grep -c -i Wats.n arwiki-latest-pages-articles.xml
793
real 0m2.628s
user 0m2.168s
sys 0m0.457s
1 dakikadan 2 saniyeye indik. Hiç fena sayılmaz. Ama günlük olarak genellikle ag
kullanıyorum, o yüzden bir de onun performansına bakalım:
$ ag --version
ag version 0.31.0
Features:
+jit +lzma +zlib
$ time ag -c -i Wats.n arwiki-latest-pages-articles.xml
ERR: Skipping arwiki-latest-pages-articles.xml: pcre_exec() can't handle files larger than 2147483647 bytes.
Görünen o ki, en azından ag
nin bu sürümü GBlar mertebesindeki metin dosyalarını işleyemiyor. Simdi sıra geldi yeni araçları denemeye:
icgrep
ile başlayalım ve aynı şeyi deneyelim:
$ icgrep --version
LLVM (http://llvm.org/):
LLVM version 3.5.0svn
Optimized build.
Built Nov 4 2015 (10:54:34).
Default target: x86_64-apple-darwin15.4.0
Host CPU: core-avx2
$ time icgrep -c -i Wats.n arwiki-latest-pages-articles.xml
793
real 0m3.022s
user 0m2.028s
sys 0m0.993s
Gördügümüz gibi icgrep
nerede ise GNU grep
kadar hızlı bu basit düzenli ifade işlemi için.
Aynı seyi ripgrep
ile deneyelim:
$ rg --version
0.2.6
$ time rg -c -i Wats.n arwiki-latest-pages-articles.xml
793
real 0m4.340s
user 0m3.780s
sys 0m0.560s
Bu durumda ripgrep
, icgrep
ve GNU grep
e kıyasla biraz daha yavaş görünüyor.
Bu düzenli ifade programlarının performansına dair çok kaba saba da olsa bir fikrimiz oluştuğuna göre, biraz daha ilginç ve Unicode ile ilgili bir düzenli ifade denemesi yapabiliriz: 3.1 GB Arapça metin içinde acaba hiç Yunan harfi geciyor mu, geçiyorsa kaç tane?
OS X
ile gelen BSD grep
Unicode ifadelerini desteklemediği icin onu kıyaslama dışında bırakıyoruz. ag
nin de 3.1 GB büyüklüğünde dosya ile basa çıkamadığını yukarıda görmüştük. Dolayısı ile geriye sadece GNU grep
, icgrep
, ve ripgrep
kalıyor:
$ time /usr/local/bin/grep -P -c '\p{Greek}' arwiki-latest-pages-articles.xml
14480
real 0m27.130s
user 0m26.580s
sys 0m0.510s
Yukarıdaki sorguya gore GNU grep
ile 3.1 GB'lik dosya içinde geçen 14.430 tane Yunan harfinin varlığını tespit etmek 27 saniye sürdü.
Daha iyisini yapabilir miyiz? icgrep
ile deneyelim:
$ time icgrep -c '\p{Greek}' arwiki-latest-pages-articles.xml
14480
real 0m3.203s
user 0m2.168s
sys 0m1.034s
Üniversitedeki araştırma geliştirme çabasının icgrep
üzerindeki olumlu etkisi burada kendini gösteriyor: yaklasık 3 saniyede aynı işlemi tamamlayabildik.
Peki ama ripgrep
aynı aramayi ne kadar sürede yapabilecek?
$ time rg -c '\p{Greek}' arwiki-latest-pages-articles.xml
14480
real 0m6.800s
user 0m6.230s
sys 0m0.540s
Görünen o ki, bu tür düzenli ifade aramalarinda, ripgrep
, icpgrep
ten yaklaşık 2 kat daha yavaş ama yine de GNU grep
e kıyasla çok daha hızlı.
O halde bu maçın galibi kim? Bu basit soruya basit bir cevap vermek mümkün degil. Cevap biraz da sizin durumunuza baglı. ICgrep yoğun bir araştırma geliştirme çabasının ürünü, akademik ortamdan çıkan, yepyeni teknikler kullanan bir araç. Lakin kolayca kurup denemek istiyorsanız bu sadece MacOS / OS X ortamında mümkün. Eger kaynak kodu indirip GNU/Linux ortaminda derleyip kullanmaya çalısacaksanız kolay gelsin.
Diger yandan, ripgrep
de epey hızlı ve akıllıca davraniyor. MacOS, GNU/Linux ve MS Windows için kolayca kurabileceginiz çalıştırılabilir dosyaları sundugu için hemen kullanmaya başlayabilirsiniz. Benim açımdan 'Silver Searcher' yani ag
komutunun yerine geçmeye aday.
ICgrep'in gelistiricisi ile ripgrep'in gelistiricisi arasindaki ilginç bir tartışmayı ve değişik performans kıyaslamalarını su adresten takip edebilirsiniz: https://news.ycombinator.com/item?id=12586928. Ayrıca https://github.com/BurntSushi/ripgrep/issues/63 adresinde de benzer konular ele alinmis ripgrep geliştiricisi tarafından.
Düzenli ifadelerle ilgili daha bilimsel ve detaylı bir performans kıyaslaması için http://sljit.sourceforge.net/regex_perf.html adresini ziyaret edebilirsiniz ama bu calisma henüz ICgrep ve ripgrep'e dair kıyaslamaları içermiyor.
Kaynak: Faster, RegEx! Match! Match! (Which Regular Expression Utility is the Fastest?)
Kucuk bir not: bu araclari benchmark ederken, OS'in disk cache'ini temizlemek daha tutarli sonuclar verebilir.