Hatena::ブログ(Diary)

くふんを狙え

navi

2008-04-14

80 howm-mode.vim (2-43) データ量増大による検索速度の低下を回避する( globpath() )

ダウンロード

はじめにダウンロードのためのURL

http://khkh.o0o0.jp/vim/howm_vim.patch.20080414

欠陥「検索速度の低下」

howm-mode.vim にはいくつのかの欠陥がある。その一つが検索速度の低下である。今回は、その検索速度の低下に対処したいと思う。

howm の構造を簡単に説明していまうと、「ファイル(メモ)を作成し、必要に応じてそれらを grep 検索する」これだけのものだ。浮沈TODOだとか、予定一覧だとか、action-lock だとか言ってるが、それらも検索機能(一覧表示)か、メモ作成の補助かにすぎない。grep による全文検索を行っている以上、ファイルが増えるとどうしても速度低下が起きる。

しかし、howmも4年以上使ってると、起動や検索が耐えられないくらい遅くなります;;

仕方なく、前の3年分のデータをバックアップ後に削除しました。多少(以前に比べると劇的に)快適になりました。

http://d.hatena.ne.jp/smeghead/20080325/heavy

引用元では本家 howm だが howm-mode.vim も例外ではない。むしろ、vimgrep を使用していれば、事態はより深刻である。すべてのログをメモリに読み込むわけだから、速度はお世辞にも速いとは言いがたい。私の環境ではデータはたかだか三ヶ月分だが、もうすでに初回検索に10秒程度かかる。

対応策「全文検索しない」

この問題を回避するには、「キャッシュ」や「インデックス」が妥当な手段だろう。ただ、私が思うに、これらの手段はいささか面倒すぎる。なので、私は「全文検索しない」ことにした。そもそも、全文検索しようとするから時間がかかってしまう。全文検索などやめてしまえばいい。どうせ普段検索するのは、その日と前後一週間程度だろう。必要なファイルだけを検索すればいい。

具体策「globpath()」

Vim には globpath() という関数がある。Version 6 から追加された関数だ。これを利用して、不必要なファイルで vimgrep しないようにしてやる。

for file in split(globpath(searchPath, '**/*.*'), "\<NL>")
  if isdirectory(file) | continue | endif
  let file = escape(file, ' ')
  silent! execute hide 'vimgrepadd /'. searchWord .'/j' file
endfor

おおよそこんなところだ。 vimgrepadd を使えば、quickfix リストに検索結果を徐々に追加していける。

無視するファイルの設定「グローバルオプション wildignore/グローバル変数 howm_wildignore」

「で、無視するファイル云々はどうなったの」そんな疑問がわくと思う。ここで重要なのが「 globpath() はグローバルオプション wildignore を考慮する」ということだ。 wildignore を使えば、globpath() で列挙されるファイルを抑制できる。既にこういう便利なオプションがあるのだから、これを利用しない手はない。ただ、グローバルオプションをそのまんま変更すると影響が大きすぎるため、グローバル変数 howm_wildignore を用意してやる。それを try とかでくくってだな、うん。コードを書いても面倒なだけなので、必要なら使ってみてほしい。

設定例を挙げておく。自分はとりあえず、2008年の1月2月のファイルは無視したい。だから、以下のようにしてある。特に面白い設定でもない。

let g:howm_wildignore = '*/2008-0[12]*.howm'

誤爆する可能性もあるだろうが、まあいざとなったら let g:howm_wildignore = '' とでもしてから、検索してやれば全文検索になるので、問題はない。

wildignore の設定については、ヘルプを参照すると良い。globpath() についてもついでに調べた方が良いかもしれない。

:h globpath()
:h wildignore

小さいけど大きな修正「タイトル行でもキーワードを強調」

あと、小さな修正として、タイトル行でもキーワードや予定などが強調されるよう修正した。

smegheadsmeghead 2008/04/14 21:53 (私は「全文検索しない」ことにした)++
目から鱗のアイデアです。本家でも採用されると嬉しいオプションだと思いました。

名無し名無し 2008/04/14 22:21 更新お疲れさまです。
試しに、除外したい拡張子を指定したのですが、もうまく利かないです。
.vimrcに、
let g:howm_wildignore = ’*/*.js’
として、*.howm の文中のhoge は検索し、*.js は無視させる、みたいのことをしたのですが。

eclipse-aeclipse-a 2008/04/14 22:33 はじめまして。恥ずかしながら、本家をまったくさわったことがありません。
やはり本家では、データ増大への対処手段は提供されていないのでしょうか?
ないのだとすれば、全文検索をやめると複雑になって使いにくくなるからでしょうかね。(たださすがに毎日使って4年分となると vimgrep のようにメモリに読み込まずとも、相当な速度低下が予想されますが……)

howm-mode.vim では、マスク(無視するファイルのパターン)をもっと手軽に変更する手段などが要求されてくるのではと考えています。本家もよくなるといいですね!

eclipse-aeclipse-a 2008/04/14 22:49 > 名無しさん
報告ありがとうございます。

私の環境で test.js のような形でファイルを置き、同様に vimrc に howm_wildignore を設定してテストしたところ、正しく動作しているように思います。*.howm 中の「あいうえお」はヒットし、*.js 中の「あいうえお」はヒットしませんでした。

もしかすると +wildignore でコンパイルされていないのかもしれません。

:ec has(’wildignore’)

表示が0だった場合には wildignore オプションがそもそも存在していません。その場合は動作しません。構成 normal の中に +wildignore は含まれているので使用したのですが、チェックしておいた方がよかったのかもしれません。申し訳ありません。

表示が1だった場合は、本当に原因不明です。パッチが正しく当たっていない可能性もありますし、そもそもアップロードされているファイルが間違っているのかもしれません。ぜひ、詳しい状況報告をお願いします。

名無し名無し 2008/04/15 00:17 :ec has(’wildignore’)
1
を返しました。Vimは香り屋版を使っています。

自分なりに調べたところ、検索方法によって、利くものと利かないものとがあるようです。
,,g 除外されない
,,v 除外される
,,m 除外される
,,s 除外される
となり、先ほどのレスでは、,,g の結果だけを見て、書き込んでしまいました。
前からの癖で ,,g をつい使ってしまいがちに。。。
,,g 以外の検索方法であれば問題なく利くので、使用上問題ないです。
お騒がせして申し訳ありませんでした。

eclipse-aeclipse-a 2008/04/15 00:33 > 名無しさん
お騒がせして〜<いえいえ、何度も報告ありがとうございます。原因は「 vimgrep 以外では globpath() を使用していないから」だったのですね!原因が分かってスッキリしました。本当にありがとうございます。

そういえば、vimgrep のみで使用できることが、はっきりとエントリ中に書かれていませんね。そこまで気がついていませんでした。申し訳ありません。

vimgrep 以外でも globpath() を使用できるようにしたほうがいいかもしれませんね。検討します。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/eclipse-a/20080414/1208174793