Es stellt sich heraus, dass die stark schwankende Leistung mit der Müllabfuhr zusammenhängt. Jeder Aufruf der Funktion würde langsamer, bis eine Garbage Collection ausgeführt wurde. Mit Standard-Emacs wurde gc alle paar Sekunden ausgeführt, aber ich hatte eine Zeile in meinem init.el, um die Startzeit zu verbessern, die den gc-cons-Schwellwert auf 20 MB festlegte, und das bedeutete, dass gc viel seltener ausgeführt wurde, was Benchmarks verursachte melde langsamer und langsameres Timing, bis ein Gc nach ein paar Minuten ausgeführt wurde, dann würden die Zeiten sinken und wieder schnell sein.
Nach dem Zurücksetzen auf den Standardwert für die GC-Cons-Schwelle wurde das Benchmarking einfacher.
Ich habe dann mit dem eingebauten Profiler ( M-x profiler-start
) ein Speicherprofil erstellt und festgestellt, dass Aufrufe von syntax-ppss die meisten Zuweisungen verursachten. Nach einigen Optimierungen, um syntax-ppss seltener aufzurufen, habe ich eine akzeptable Leistung erzielt.
Die Verwendung des JIT-LOCK-Modus (Hinzufügen einer Funktion über das JIT-LOCK-Register) scheint der einfachste Weg zu sein, um eine zuverlässige Sperrung für mehrzeilige Schriften zu erreichen. Daher habe ich diese Methode gewählt.
Bearbeiten: Nachdem ich festgestellt habe, dass die Leistung in sehr großen Puffern immer noch nicht gut genug ist, habe ich viel Zeit damit verbracht, die CPU-Nutzung und -Zuordnung zu optimieren und die Leistungsverbesserungen mit dem integrierten Emacs-Profiler ( M-x profiler-start
) zu messen . Emacs stotterte und blieb jedoch hängen, wenn er schnell durch sehr große Puffer blätterte. Das Entfernen der JIT-Lock-Funktion, mit der ich mich registriert habe, jit-lock-register
würde das Stottern und Hängen beseitigen, aber das Profilieren zeigte, dass die JIT-Lock-Funktion in ungefähr 8 ms abgeschlossen ist, was für ein reibungsloses Scrollen schnell genug sein sollte. Das jit-lock-register
Problem wurde behoben, indem der Aufruf von und stattdessen die Verwendung eines regulären Übereinstimmungsprogramms für Schriftsperren-Schlüsselwörter entfernt wurde.
TLDR: Das war langsam und würde stottern:
(defun my-font-lock-function (start end)
"Set faces for font-lock between START and END.")
(jit-lock-register 'my-font-lock-function)
Dies zu tun war schnell und würde nicht stottern:
(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))))