Hatena::ブログ(Diary)

hchbaw記

2010-04-05

zshの補完関数_gitを速くしたい!

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

期待どうりの動作をしていないです!ゴメンナサイゴメンナサイm(__)m

この記事の通りにしちゃうと補完関数が壊れちゃいます!真似しないで!

ごめんなさい m(__)m


補完が遅くて耐えられないという向きには __git_files() 関数を置き

かえてしまうことで、なにかしらのヒントとなるかもしれません…

いいかげんなエントリになってしまって本当にごめんなさい。

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>





いまのところ結果として、およそ 1/60 になったのですけれども

動作があっているかどうかとか、測定方法とかあんまり自信がないです><

期待どうりの動作をしているか怪しいので、気をつけてくださいねm(__)m

期待どうりの動作をしていないです!ゴメンナサイm(__)m

例えば、.git ディレクトリが出てきちゃったりなど、最早 index files ではなくなっちゃったりします!


Linuxカーネルのように、ファイルの数が極端に多くなると顕著になると思うのだけれども、例えば`git checkout -- [TAB]`で全然結果が返ってこなくっていったいどうなってしまったというのだ!という局面があります。

それでちょこちょこいじってみているのだけれども忘れそうなのでメモです。

補完システムのトレースを取りたい。

_complete_debug (^X?) で、普通に補完するのだけれども補完システムのトレースをキャプチャーできます。(xtrace をセットして戻している)

例えば、プロンプトへ、"git checkout -- C-x ?" もしくは "git checkout -- M-x _complete_debug[ENTER]" とやると "Trace output left in /tmp/zsh4250git1 (up-history to view)" と出ます。(文字どうり履歴に表示用のコマンドが入ります。^^)

プロファイラはないの?

zsh/zprof を使うことで、`gprof`のような出力をするプロファイルリング結果を得られます。例えば下のような感じです。

http://gist.github.com/356323

で、この結果の self の覧を見るとよくわかるのだけれども、_multi_parts が 98% 費しているのがわかりました。これを踏まえて、

まず、_multi_parts ってなあに?

"zshの"というまさにその名を冠するにふさわしい(、と個人的におもっている)『zshの本 (エッセンシャルソフトウェアガイドブック)』によると、

指定した Delim ごとに止まるような階層的な補完を行なう。

...

sysctl コマンドの補完例が分かりやすい設定例となっている。

とあります。

ということは、__git_files 内では _multi_parts ではなくって _files でよいのじゃなかろうか?という勝手な見解にもとづき、

  _wanted files expl 'index file' _multi_parts $@ - / files

  _wanted files expl 'index file' _files files

としてみちゃった!

あんまり回数多く試していないので、期待どうりの動作をしているのかどうなのかすんごい不安なのですけれども、数字だけを見ると、

16371.33  8185.67   99.84%     45.05    22.53    0.27%  _git

だったのが、

251.91   251.91   97.58%      8.24     8.24    3.19%  _git

となり、全体でおよそ 1/60〜1/65 くらいになりました。http://gist.github.com/356397


というわけで __git_files を以下の定義で上書きしています。

#autoload +X

__git_files () {
  local expl files ls_opts opts gitdir gitcdup

  zparseopts -D -E -a opts -- -cached -deleted -modified -others -ignored -unmerged -killed

  gitdir=$(_call_program gitdir git rev-parse --git-dir 2>/dev/null)
  __git_command_successful || return

  gitcdup=$(_call_program gitcdup git rev-parse --show-cdup 2>/dev/null)
  __git_command_successful || return

  ls_opts=("--exclude-per-directory=.gitignore")
  [[ -f "$gitdir/info/exclude" ]] && ls_opts+="--exclude-from=$gitdir/info/exclude"

  files=$(_call_program files git ls-files -z --full-name $ls_opts $opts -- $gitcdup 2>/dev/null)
  __git_command_successful || return
  files=(${(ps:\0:)"$(__git_files_relative $files)"})
  __git_command_successful || return

  # TODO: _multi_parts vs _files
  #_wanted files expl 'index file' _multi_parts $@ - / files
  _wanted files expl 'index file' _files files
}

zsh のバージョンは

> echo $ZSH_VERSION
4.3.10-dev-1-cvs0311

で試しています。

サブディレクリ内からではあいかわらず遅いです(T^T;

期待どうりの動作をしているか怪しいので、気をつけてくださいねm(__)m

例えば、.git ディレクトリが出てきちゃったりなど、最早 index files ではなくなっちゃったりします!

さてさて、そのうち _multi_parts と _files を読みます!



>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

色々だめでして、何が駄目かというのは

  _wanted files expl 'index file' _multi_parts $@ - / files

  _wanted files expl 'files' _files

という改悪をしていることになってます!(T^T;

つまりどうせやるのだったらば、いさぎよく __git_files 関数自体を

__git_files () {
  local expl

  _wanted files expl 'file' _files
}

http://gist.github.com/356639 としないと意味がないよね!ということですよね。

本当にゴメンナサイ。m(__)m

http://gist.github.com/356323 の結果を見て、耐えられない、という

向きにはもしかしたらば有用なのかもしれません…



というわけで、

期待どうりの動作をしていないです!ゴメンナサイゴメンナサイm(__)m

この記事の通りにしちゃうと補完関数が壊れちゃいます!真似しないで!

ごめんなさい m(__)m

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

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


画像認証

トラックバック - http://d.hatena.ne.jp/hchbaw/20100405/1270479457