vimdoc-ja-working icon indicating copy to clipboard operation
vimdoc-ja-working copied to clipboard

deploy/Generate new documentを速くする

Open koron opened this issue 3 years ago • 8 comments

現在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)~ めんどいのでやらない

koron avatar Dec 18 '21 02:12 koron

いまちょっとやってます。成果でたらPRします。

koron avatar Dec 19 '21 07:12 koron

#999 にて成果を公開。

けれども手元のWindowsではかなり遅くなってしまい もともとの make html が 2m30s 程度だったのに対して

  • make html217m
  • make -j8 html2 で 3m14s
  • make -j16 html2 で 2m54s

ぶっちゃけ地獄の遅さ。

ボトルネックはほぼほぼ tohtml#Convert2HTML なのは確認した。

推測では 2html.vim の読み込みパースが別プロセスになるので もろもろキャッシュが効かなくなるんじゃないか、あたり。

koron avatar Dec 19 '21 09:12 koron

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 で十分に速くはなりそう。

koron avatar Dec 19 '21 09:12 koron

Windowsで遅い原因の1つには taglist(".*") で tags-ja を読むのが遅い(約4秒かかる)ことがわかった。 パラレルでは140回やるので約9分余分にかかってる。

読み込んで整形したものを js_encode() & writefile() で書き出し、 それを readfile() & js_decode() したら(≒JSONでのキャッシュにしたら)一瞬だった。

これで置き換えることで8分、いや恐らく9分は縮められそう。

koron avatar Dec 19 '21 16:12 koron

tags-jaにJSON形式のファイルキャッシュを噛ませたところ…

make html2 で 17m

これが 3m になった。


Windows でさらに並列度をあげるとこんな感じ

  • -j16 - 47s
  • -j8 - 53s

https://github.com/vim-jp/vimdoc-ja-working/pull/999/commits/566876ba251e35cdfc84392b3d11bd0b33b2626b

koron avatar Dec 19 '21 16:12 koron

残課題:

  • [ ] Makefileの依存関係見直し (mandatory)
  • [x] 2html.vimのボトルネックの把握 (optional)
  • [ ] 実行時のプログレス表示、検討・改善 (optional)

koron avatar Dec 20 '21 00:12 koron

ボトルネックはほぼほぼ 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) の影響が強くなっていた。

koron avatar Dec 20 '21 00:12 koron

GHA上にて 220秒くらいだったものが130秒くらいに高速化することを確認した。 https://github.com/vim-jp/vimdoc-ja-working/pull/999#issuecomment-1001407599

koron avatar Dec 27 '21 08:12 koron