@kyanny's blog

My thoughts, my life. Views/opinions are my own.

`org-capture` がとても遅い

55,000 行の org ファイルに追記するとき、org-capture でテンプレートを選んだあと、テンプレートが埋め込まれたバッファが表示されるまでの時間がとても遅い。前から遅かったけど一分以上待たされるようになってきた。思考を中断されて、テンポが悪くて困っている。

ファイルが大きすぎるせいだろうけど、とりあえずプロファイルを取ってみた。

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

遅い関数呼び出しは以下の三つ。

  1. sha1
  2. basic-save-buffer-2
  3. 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 で書かれた関数を読んでるだけだし。