散々既出で今更だけどmacOSデフォルトのgrepがめちゃ遅だった
(あまりに内容が雑なのでポエム扱いで)
そこそこデカいファイルを扱っていたら気になったのでメモ. 一時期 grepが10倍速くなった と話題になったりしてましたが自分のユースケースでは最大2,000倍程度の速度差がありました (記事の内容とは関係ない部分のようですが).
TL;DR;
通常はmacOSデフォルトのBSD版grepを, Perl拡張などを使う時のみGNU版grepを使っています (全部GNU版でもいいかなと思うもOSデフォルトを弄ると色々壊れそうで怖かったので…). 普段は速度的に気にならなかったのですが, そこそこデカいファイル, とはいえ300MB程度ですがBSD版grep使ったら遅くてつらみを背負いました.
計測
対象はマルチバイト中心で約300MB (26,000行) のxmlファイルで行いました.
特にオプション等は使わずに (grep $pattern $file
) 雑に計測しました (ignore-caseとか考慮すると結構変わるかも).
(real/user/sys) | BSD grep 2.5.1 |
GNU grep 3.1 |
---|---|---|
'芸術' |
0m5.502s (0m4.959s, 0m0.142s) | 0m0.007s (0m0.001s, 0m0.002s) |
'芸術[^家]' |
0m6.280s (0m5.292s, 0m0.152s) | 0m0.003s (0m0.001s, 0m0.001s) |
'国内.*芸術' |
0m5.109s (0m4.891s, 0m0.103s) | 0m0.003s (0m0.001s, 0m0.002s) |
1つ目は単なる一致, 2つ目は雑な正規表現, 3つ目はbacktrackするであろう正規表現で試しました. どのパターンでも750〜2000倍程度とかなりの速度差が出ました. 今回は面倒なので条件や理由は探求しません. 詳しい人いたら教えてくだし
インストール
Homebrewでビャっと入れときましょう. デフォルトだと ggrep
という名前のコマンドとしてインストールされますが, --with-default-names
オプションを付けるとOSデフォルトの grep
を隠すようになります.
brew tap homebrew/dupes brew install homebrew/dupes/grep # --with-default-names
おまけ
パイプラインを使う (cat $file | grep $pattern
) と一方的に遅くなると思っていたけどそうでもない模様. GNU版は50〜90倍程度遅くなったがBSD版は僅かに速いという結果に (何故)
(real/user/sys) | BSD grep 2.5.1 |
GNU grep 3.1 |
---|---|---|
'芸術' |
0m4.962s (0m4.830s, 0m0.222s) | 0m0.166s (0m0.011s, 0m0.206s) |
'芸術[^家]' |
0m4.982s (0m4.891s, 0m0.223s) | 0m0.274s (0m0.011s, 0m0.214s) |
'国内.*芸術' |
0m5.054s (0m4.927s, 0m0.231s) | 0m0.162s (0m0.010s, 0m0.205s) |