爲何GNU grep如此之快?

編注:這是GNU grep的原做者Mike Haertel 在FreeBSD郵件列表中對 「GNU grep爲何比BSD grep要快」 所作的回答,下面是郵件正文內容:html

Gabor 您好,算法

我是GNU grep的原做者,同時也是一名FreeBSD用戶,不過我一直使用的是-stable版本(也就是更老的版本),而沒怎麼關注-current版本。緩存

可是,當我無心間翻閱-current版的郵件列表時,偶然發現了一些關於BSD grep與GNU grep性能的討論,你可能也注意到了那些討論。bash

無論怎麼說,僅供參考吧,下面是一些簡單的總結,關於爲何GNU grep如此之快。或許你能借鑑其中的一些思想運用到BSD grep中去。性能

  • 技巧1:GNU grep之因此快是由於它並不會去檢查輸入中的每個字節。
  • 技巧2:GNU grep之因此快是由於它對那些的確須要檢查的每一個字節都執行很是少的指令(操做)。

GNU grep使用了很是著名的Boyer-Moore算法(譯者注:BM算法,是一種很是高效的字符串搜索算法,通常狀況下,比KMP算法快3-5倍,具體可查看這篇講解很是詳細的文章:grep之字符串搜索算法Boyer-Moore由淺入深(比KMP快3-5倍)),該算法首先從目標字符串的最後一個字符開始查找,而且使用一個查找表,它能夠在發現一個不匹配字符以後,計算出能夠跳過多少個輸入字符並繼續查找。優化

GNU grep還展開了Boyer-Moore算法的內部循環,並創建了一個Boyer-Moore的delta表,這樣它就不須要在每個展開的步驟進行循環退出判斷了。這樣的結果就是,在極限狀況下(in the limit),GNU grep在須要檢查的每個輸入字節上所執行的x86指令不會超過3條(而且還跳過了許多字節)。翻譯

你能夠看看由Andrew Hume和Daniel Sunday 1991年11月在「Software Practice & Experience」上發表的論文「Fast String Searching」,該文很好的討論了Boyer-Moore算法的實現技巧,該文有免費的PDF在線版(譯者注:點這裏查看或下載)。code

一旦有了快速搜索,這時你會發現也須要一樣快速的輸入。htm

GNU grep使用了原生Unix輸入系統調用並避免了在讀取後對數據進行拷貝。blog

並且,GNU grep還避免了對輸入進行分行,查找換行符會讓grep減慢好幾倍,由於要找換行符你就必須查看每一個字節!

因此GNU grep沒有使用基於行的輸入,而是將原數據讀入到一個大的緩衝區buffer,用Boyer-Moore算法對這個緩衝區進行搜索,只有在發現一個匹配以後纔會去查找最近的換行符(某些命令參數,好比-n會禁止這種優化)。

最後,當我還在維護GNU grep的時候(15+年前……),GNU grep也嘗試作一些很是困難的事情使內核也能避免處理輸入的每一個字節,好比使用mmap()而不是read()來進行文件輸入。當時,用read()會使大部分Unix版本形成一些額外的拷貝。由於我已經再也不GNU grep了,因此彷佛mmap已經再也不默認使用了,可是你仍然能夠經過參數–mmap來啓用它,至少在文件系統的buffer已經緩存了你的數據的狀況下,mmap仍然要快一些:

$ time sh -c 'find . -type f -print | xargs grep -l 123456789abcdef'
  real  0m1.530s
  user  0m0.230s
  sys   0m1.357s
$ time sh -c 'find . -type f -print | xargs grep --mmap -l 123456789abcdef'
  real  0m1.201s
  user  0m0.330s
  sys   0m0.929s

[這裏使用的輸入是一個648M的MH郵件文件夾,包含大約41000條信息]

因此即便在今天,使用–mmap仍然能夠提速20%以上。

總結:

  • 使用Boyer-Moore算法(而且展開它的內層循環)。

  • 使用原生系統調用來創建你的緩衝輸入,避免在搜索以前拷貝輸入字節。(不管如何,最好使用緩衝輸出,由於在grep的經常使用場景中,輸出的要比輸入的少,因此輸出緩衝拷貝的開銷要小,而且能夠節省許多這樣小的無緩衝寫操做。)

  • 在找到一個匹配以前,不要查找換行符。

  • 嘗試作一些設置(好比頁面對齊緩衝區,按頁大小來讀取塊,選擇性的使用mmap),這樣可使內核避免拷貝字節。

讓程序變得更快的關鍵就是讓它們作更少的事情。;-)

致禮

Mike


原文連接: FreeBSD Mailing Lists 翻譯: 伯樂在線 - 敏敏

相關文章
相關標籤/搜索