grabやagは本当にgrepよりも速い?
grepよりも高速なgrepの実装「grab」、grabよりも高速な「ag」。すなわち、grep < grab < ag。それを信じてgrepからgrabやagに移行する人がいるらしい。
ag (The Silver Searcher) の作者は、自らベンチマークを行いagがgrabよりも30倍高速であることを示したそうです。
そこで、agやgrabがどれくらい高速なのか試してみました。
grabのビルド
画面の右側にある「Download ZIP」よりソースコードをダウンロードし、コンパイルしました。
$ wget https://github.com/stealth/grab/archive/master.zip $ unzip -q master.zip $ cd grab-master $ make
agのビルド
画面の右側にある「Download ZIP」よりソースコードをダウンロードし、コンパイルしました。
$ wget https://github.com/ggreer/the_silver_searcher/archive/master.zip $ unzip -q master.zip $ cd the_silver_searcher-master $ ./build.sh
パフォーマンス比較
/etcディレクトリ配下を再帰的に検索してみました。公平に測定するため、Cロケールで比較しています。grepは Red Hat Enterprise Linux 6にバンドルされているgrep-2.6.3、grabとagは本稿執筆時点でのgitバージョンです。
$ export LANG=C $ time -p /bin/grep -r http /etc >/dev/null real 2.21 user 1.89 sys 0.31 $ time -p ./grab -r http /etc/ >/dev/null real 0.08 user 0.05 sys 0.02 $ time -p ./ag http /etc/ >/dev/null real 0.48 user 0.09 sys 0.67
言われているように、grabやagはgrep-2.6.3よりもかなり速いという結果になりました。
しかし、その後の調査で、grep-2.6.3だけはシンボリック・リンクを追跡することが判明しました。grep-2.11までは、-rと-Rは同じで、どちらもシンボリック・リンクを追跡する動作となっています。grep-2.12からは、grabやagと同様に-rはシンボリック・リンクを追跡しないように動作変更されています。
これでは不公平なので、grep-2.21で再検証してみました。
$ export LANG=C $ time -p grep -r http /etc/ >/dev/null real 0.04 user 0.01 sys 0.02
結果はgrepの勝利でした。続いて別のディレクトリ/usr/share/doc配下を検索してみましたが、やはりgrepが勝利しました。
$ time -p grep -r http /usr/share/doc/ >/dev/null real 0.31 user 0.19 sys 0.11 $ time -p ./ag http /usr/share/doc/ >/dev/null real 4.92 user 1.26 sys 7.33 $ time -p ../grab-master/grab -r http /usr/share/doc/ >/dev/null real 0.74 user 0.52 sys 0.22
ということで、予想に反してgrep > grab > agとなりました。