55,000 行の org ファイルに追記するとき、org-capture でテンプレートを選んだあと、テンプレートが埋め込まれたバッファが表示されるまでの時間がとても遅い。前から遅かったけど一分以上待たされるようになってきた。思考を中断されて、テンポが悪くて困っている。
ファイルが大きすぎるせいだろうけど、とりあえずプロファイルを取ってみた。
- Profiling (GNU Emacs Lisp Reference Manual)
- Profiling Performance in Emacs | Ian Y.E. Pan
- Emacsのプロファイリング機能の紹介 #emacs-lisp - Qiita
profile.el
M-x profiler-start (cpu+mem) C-c n n j C-c C-c M-x profiler-stop M-x profiler-report
elp
(setq elp-function-list '(org-capture)) M-x elp-instrument-list RET nil RET M-x elp-results
Function Name Call Count Elapsed Time Average Time ============= ========== ============ ============ org-capture 1 85.521921 85.521921
遅い関数呼び出しは以下の三つ。
sha1
basic-save-buffer-2
org-persist--normalize-associated
のなかで呼び出されてるコンパイル済み関数(具体的に何かわからず)
解せないのは、sha1
を呼び出してる undo-fu-session--save-impl
を読んで、sha1
の呼び出され方を見ると current-buffer
を渡してるようなので、org ファイルのバッファを開いた状態で (sha1 (current-buffer))
すると一秒もかからず結果が返ってくる。バッファに何か書き足して再評価するとちゃんと違う結果になるので、毎回ちゃんと計算している。つまり sha1
は遅くないはずなのに、ここで 85 秒のうちの 32% も費やすはずがないのだが。
basic-save-buffer-2
はどこが遅いのかわからない。その直下の write-region
の呼び出しには CPU 0% なので、この関数内のどこかが遅いのは確からしいのだが。
気になったのは、どちらもメモリ消費量が多い(900 MB 以上)。そもそもプロファイル全体で 1.9 GB 以上のメモリを消費している。まあ、明らかに大きい気がする。org ファイルのサイズ自体は 3.1M しかないのだけど。
なんとなく、バッファが巨大すぎてメモリを使いすぎており、スワップでもしているのかもしれない。とするとファイルを分割して小さくするくらいしかできることがなさそう。sha1
に至っては内部で C で書かれた関数を読んでるだけだし。