vimdoc-ja-working
vimdoc-ja-working copied to clipboard
deploy/Generate new documentを速くする
現在deployのGenerate new documentがボトルネックになっている。
例えば このビルド では全体で 3m7s のうち 実に 2m52s (約92%) がGenerate new document に費やされている。
Generate new document は make html を実行しており、 https://github.com/vim-jp/vimdoc-ja-working/blob/7ebdd1682ec7b457cc2e4fa3b60ffb756c520266/Makefile#L12-L16
これは tools/buildhtml.vim で行われてる。
buildhtml.vim は MakeHtmlAll で全 *.jax を *.html に変換してから、各ファイルにJekyll用のYAMLヘッダーを付けている。 ファイルが多いのに加えてこの部分が順次直列に変化するために時間がかかっていると推測される。 よってこの部分をファイル単位で並列化できれば高速化が期待できる。
解決策案
MakeHmtlAllはファイルを列挙して MakeHtml を呼び出すようになっている。 なのでラッパースクリプトとして、 引数でファイルを1つ受け取ってMakeHtmlを実行しYAMLヘッダーを付与する スクリプトを作れば、 makeファイルによる呼び出し側から並列度をコントロールできるようになると考えられる。
Vim内で並列化することはほぼ不可能(terminalとか駆使すればできるかもだけど)なので やらないほうが得策。
残課題
- [ ] 一部ファイルのファイル名が異なる (mandatory)
- [ ] Makefileの依存関係見直し (mandatory)
- [x] ~2html.vimのボトルネックの把握 (optional)~ 手を入れるほどではなかった
- [x] ~実行時のプログレス表示、検討・改善 (optional)~ めんどいのでやらない
いまちょっとやってます。成果でたらPRします。
#999 にて成果を公開。
けれども手元のWindowsではかなり遅くなってしまい
もともとの make html が 2m30s 程度だったのに対して
make html2で 17mmake -j8 html2で 3m14smake -j16 html2で 2m54s
ぶっちゃけ地獄の遅さ。
ボトルネックはほぼほぼ tohtml#Convert2HTML なのは確認した。
推測では 2html.vim の読み込みパースが別プロセスになるので もろもろキャッシュが効かなくなるんじゃないか、あたり。
FreeBSDでの計測結果 time gmake -j{n} html2
- 1 -
real 3m26.255s - 2 -
real 1m43.496s - 3 -
real 1m18.743s - 4 -
real 1m6.536s
んーWindowsがとりわけ遅いってことかなぁ?
念のため同FreeBSDでの time gmake html の結果…
real 2m37.966s
user 2m34.434s
sys 0m0.701s
おおよそ GitHub Actions の machine と同じ速度感。 なので make -j2 html2 で十分に速くはなりそう。
Windowsで遅い原因の1つには taglist(".*") で tags-ja を読むのが遅い(約4秒かかる)ことがわかった。
パラレルでは140回やるので約9分余分にかかってる。
読み込んで整形したものを js_encode() & writefile() で書き出し、
それを readfile() & js_decode() したら(≒JSONでのキャッシュにしたら)一瞬だった。
これで置き換えることで8分、いや恐らく9分は縮められそう。
tags-jaにJSON形式のファイルキャッシュを噛ませたところ…
make html2 で 17m
これが 3m になった。
Windows でさらに並列度をあげるとこんな感じ
-j16- 47s-j8- 53s
https://github.com/vim-jp/vimdoc-ja-working/pull/999/commits/566876ba251e35cdfc84392b3d11bd0b33b2626b
残課題:
- [ ] Makefileの依存関係見直し (mandatory)
- [x] 2html.vimのボトルネックの把握 (optional)
- [ ] 実行時のプログレス表示、検討・改善 (optional)
ボトルネックはほぼほぼ tohtml#Convert2HTML なのは確認した。
この誤解は観測データが偏っていたことによるもの。 ファイルによって tohtml#Convert2HTML が重いものと、そのあとの s:MakeLink が重いものがある。 結果的に前者が重いファイルだけを観測に用いてたことが誤解に繋がった。
詳細
s:MakeLink は s:GetTags で1回だけ taglist() を実行し、ほぼ定数時間がかかっていた。 このかかる時間は tags-ja ファイルのサイズで決まっており、 tags-jaはmake html実行時には固定となるので定数時間である。 ただしWindowsではこの定数時間が4秒とかなり長いため 全140ファイルをそれぞれ別プロセスで変換すると 各4秒のオーバーヘッドが積み上がり9分を超える膨大なロスに繋がっていた。
一方で tohtml#Convert2HTML は対象となる *.jax のファイルサイズに実行時間が依存する。 特に tags.jax や version8.txt などは大きいのでコチラの比重が重くなり、実行時間が長くなる。
パフォーマンスを計測するにあたり過去の経験から 「時間のかかるもので測った方がボトルネックが良く見える」 という前提でファイルサイズの大きい *.jax を計測対象としたため 「tohtml#Convert2HTMLがボトルネックである」という誤解が起こった。
実際はサイズが大きいファイルは多くない。 そのため全体としては tohtml#Convert2HTML の影響よりも s:MakeLink (s:GetTags) の影響が強くなっていた。
GHA上にて 220秒くらいだったものが130秒くらいに高速化することを確認した。 https://github.com/vim-jp/vimdoc-ja-working/pull/999#issuecomment-1001407599