フォントロックパフォーマンスの最適化


13

アンカーフォントロックマッチングのバリアントを実行したい。名前のリストで始まる関数定義があり、それらの名前を関数本体内で強調表示したいです。

これを行う関数を作成し、jit-lock-registerを使用してjit-lock関数として登録しましたが、パフォーマンスがかなり悪く、大きなファイルでスクロールが遅れます。

  • パフォーマンスを測定するにはどうすればよいですか?大きなファイルで関数を呼び出すとき(elpの前後または浮動時間)にパフォーマンスを大きく変えると、0.65から12秒までかかります。フォントロックのパフォーマンスをベンチマークする推奨方法はありますか?
  • font-lock-keywordsで定義されたアンカーマッチャーとjit-lock-registerを介して関数を追加する間にパフォーマンスの違いはありますか?

編集:パフォーマンスの変動はガベージコレクションに関連しているようです。私のjit-lock関数の呼び出しは、ガベージコレクションが実行されるまで各呼び出しで連続的に遅くなり、その時点で再び高速になります。


最初の項目については、プロファイラーを試してください。
マラバルバ

私はプロファイラーを使用して、コードのどの部分に時間がかかるかを確認することもできますが、パフォーマンスが一貫していないため、変更が改善されているかどうかを判断するのは困難です。
ヨアキムハルスマン14

テストできるコードはありますか?それは私たちに大いに役立つかもしれません。
PythonNut

1
プロファイリングやマイクロ最適化に関するものではありませんが、それ自体:font-lock-studioパッケージは、フォントロックのパフォーマンスを理解するためのもう1つの有用なツールであることがわかりました。他のインタラクティブなステッピングデバッガーと同じように役立ちます-実行パスが期待したものではないことがわかり、それが主なパフォーマンスの問題です。
グレッグヘンダーショット

font-lock-studioに関するヒントをありがとう、それは素晴らしいです!ただし、jit-lock-functionsには役立ちませんが、他のすべてには役立ちます。
ジョアキムハルスマン

回答:


8

大幅に変化するパフォーマンスはガベージコレクションに関連していることがわかりました。関数の各呼び出しは、ガベージコレクションが実行されるまで遅くなります。ストックemacsでは、gcは数秒ごとに実行されていましたが、init-elにgc-cons-thresholdを20 MBに設定する起動時間を改善する行がありました。数分後にgcが実行されるまで、より遅いタイミングを報告すると、時間が急落し、再び速くなります。

デフォルトのgc-cons-threshholdに戻した後、ベンチマークが簡単になりました。

次に、組み込みのプロファイラー(M-x profiler-start)を使用してメモリのプロファイルを作成し、syntax-ppssの呼び出しが最も多くの割り当てを引き起こすことを発見したため、syntax-ppssを呼び出すための最適化の後、許容できるパフォーマンスを達成しました。

jit-lock-modeを使用する(jit-lock-registerを介して関数を追加する)ことは、複数行フォントのロックを確実に機能させる最も簡単な方法のようです。

編集:非常に大きなバッファーでパフォーマンスがまだ十分でないことがわかった後、CPUの使用と割り当ての最適化に多くの時間を費やし、組み込みのEmacsプロファイラー(M-x profiler-start)でパフォーマンスの改善を測定しました。しかし、非常に大きなバッファをすばやくスクロールすると、Emacsは依然として途切れてハングします。私が登録したjit-lock関数を削除すると、ing音jit-lock-registerとハングが削除されますが、プロファイリングにより、jit-lock関数が約8ミリ秒で完了することが示されました。呼び出しを削除しjit-lock-register、代わりに通常のfont-lock-keywordsマッチャーを使用して、問題を解決しました。

TLDR:これを行うのは遅く、どもるでしょう:

(defun my-font-lock-function (start end)
"Set faces for font-lock between START and END.")

(jit-lock-register 'my-font-lock-function)

これを行うことは速くて、どもりません:

(defun my-font-lock-function (start end)
"Set faces for font-lock between START and END.")

(defun my-font-lock-matcher (limit)
    (my-font-lock-function (point) limit)
   nil)

(setq font-lock-defaults
  (list 
     ...
    ;; Note that the face specified here doesn't matter since
    ;; my-font-lock-matcher always returns nil and sets the face on
    ;; its own.
    `(my-font-lock-matcher (1 font-lock-keyword-face nil))))

使用したコードを共有できますか?あなたのソリューションは、同じことを達成しようとしている他の人を助けるかもしれません。
マヌエルウベルティ

特定のコードを実際に使用したわけではなく、syntax-ppssを少なくしただけです。ここで問題のコードを確認できます:bitbucket.org/harsman/dyalog-mode/src/…を探してくださいdyalog-fontify-locals
ジョアキムハルスマン

私の推測ではdyalog-fontify-locals-matcherあるべきmy-font-lock-matcherとの一つがendなければなりませんlimit。とにかく、本当に面白い発見!
リンディダンサー16

@Lindydancer:はい、ありがとう。修繕。
ヨアキムハルスマン16

1
Re gc-cons-threshold:、起動時間を改善するために純粋に内部値をいじっている場合はemacs-startup-hook、後でそれらを復元するために使用することをお勧めします。
-phils
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.