anything-filelist が遅い。

anything-filelist 〜すべてのファイルを瞬時に開く方法〜 - http://rubikitch.com/に移転しましたを参考に設定してるんだけど重いというか候補の表示に時間がかかる。anything-grep-candidates-fast-directory-regexpを設定すると候補を表示するまで固まってしまう。このままだと使いずらいのでなんとかしたいと思ってなんとかしてみた。

ロケールを C にする

そういえば grep はマルチバイト文字を扱うロケールだと遅くなるというのをどこかで聞いたことがあるなと思ったので試してみる。ちなみに今のロケールの設定はこんなかんじ。

[mtym]% locale                                                     (~)
LANG=ja_JP.utf8
LC_CTYPE="ja_JP.utf8"
LC_NUMERIC="ja_JP.utf8"
LC_TIME="ja_JP.utf8"
LC_COLLATE="ja_JP.utf8"
LC_MONETARY="ja_JP.utf8"
LC_MESSAGES="ja_JP.utf8"
LC_PAPER="ja_JP.utf8"
LC_NAME="ja_JP.utf8"
LC_ADDRESS="ja_JP.utf8"
LC_TELEPHONE="ja_JP.utf8"
LC_MEASUREMENT="ja_JP.utf8"
LC_IDENTIFICATION="ja_JP.utf8"
LC_ALL=


まずは今の設定のままでの grep 所要時間。

[mtym]% time grep -ih anything /tmp/anything-filelist.all.filelist | head -n 200 > /dev/null
grep -ih anything /tmp/anything-filelist.all.filelist  2.45s user 0.03s system 99% cpu 2.488 total
head -n 200 > /dev/null  0.00s user 0.00s system 0% cpu 2.485 total


次にCに変えた場合。

[mtym]% time LANG=C grep -ih anything /tmp/anything-filelist.all.filelist | head -n 200 > /dev/null
LANG=C grep -ih anything /tmp/anything-filelist.all.filelist  0.01s user 0.04s system 116% cpu 0.043 total
head -n 200 > /dev/null  0.01s user 0.00s system 30% cpu 0.032 total


予想以上に速くなる。というわけで anything-filelist で grep 実行時に LANG の値を変えたいのだけどやり方がよくわからないので advice を設定して、grep を実行するコマンドライン文字列に手を加えることにする。

(defadvice agp-command-line (after insert-LANG=C-into-agp-command-line)
  (while (string-match "\\(^\\|| \\)\\(grep -ih\\)" ad-return-value)
    (setq ad-return-value (replace-match "LANG=C \\2" t nil ad-return-value 2))))

(ad-activate 'agp-command-line)


これで結構速くなった。

それでもなんか遅かったりする

とくにマッチする行が 200 を越える場合に。


anything-grep-candidates-fast-directory-regexp を設定している場合、shell-command-to-string を使って grep が実行されるらしい。試しに shell-command-to-string で grep を実行してみると

(shell-command-to-string "grep -ih anything /tmp/anything-filelist.all.filelist | head -n 200")
"~/archives/emacs/anything/
~/archives/emacs/anything/descbinds-anything.el
~/archives/emacs/anything/anything-complete.el

grep: 出力の書込み: Broken pipe
grep: 出力の書込み: Broken pipe
grep: 出力の書込み: Broken pipe
"


こんな感じで 200 行以降は Broken pipe のエラーが延々と出力されている。これを抑制すればよさそうなのだけど、これまたやりかたが分からない。なのでまたまた advice で grepコマンドラインに手を加えて標準エラー出力を /dev/null にリダイレクトするようにしてみる。

(defadvice agp-command-line (after insert-Redirection-of-STDERR-into-agp-command-line)
  (when (string-match "| head -n" ad-return-value)
    (setq ad-return-value (replace-match "2>/dev/null \\&" t nil ad-return-value nil))))


これで 200 行を越える場合にも候補表示に時間がかかるといったことはなくなった。pattern を入力すると一瞬で候補が表示される感じ。


というわけで、LANG 値の変更とエラー出力のリダイレクトで anything-fielist をストレスなく使うことができるようになった。ただこのコマンドラインの変更を anything-filelist のときだけにしたいのだけど、今は grep-candidates を使う source 全てに適用されてしまうのがちょっと気になる。