Optimieren der Leistung der Schriftsperre

13

Ich möchte eine Variante des verankerten Font Lock Matchings durchführen. Ich habe Funktionsdefinitionen, die mit einer Liste von Namen beginnen, und ich möchte, dass diese Namen im Funktionskörper hervorgehoben werden.

Ich habe eine Funktion erstellt, die dies ausführt und als JIT-Lock-Funktion bei JIT-Lock-Register registriert. Die Leistung ist jedoch ziemlich schlecht und das Scrollen in größeren Dateien verzögert sich.

  • Wie kann ich die Leistung messen? Wenn ich meine Funktion nur für eine große Datei aufrufe (mit Float-Zeit vor und nach oder mit Elp), ist die Leistung sehr unterschiedlich, und es dauert zwischen 0,65 und 12 Sekunden. Gibt es eine empfohlene Möglichkeit, die Leistung der Schriftsperre zu bewerten?
  • Gibt es einen Unterschied in der Leistung zwischen einem in Font-Lock-Keywords definierten verankerten Matcher und dem Hinzufügen einer Funktion über das JIT-Lock-Register?

Bearbeiten: Es scheint, dass die Variabilität der Leistung mit der Speicherbereinigung zusammenhängt. Die Aufrufe meiner JIT-Lock-Funktion werden mit jedem Aufruf langsamer, bis die Speicherbereinigung ausgeführt wird, und an diesem Punkt werden sie wieder schnell.

Joakim Hårsman
quelle
Probieren Sie für das erste Element den Profiler aus.
Malabarba
Ich kann (und habe) den Profiler auch verwendet, um zu sehen, welche Teile meines Codes Zeit benötigen, aber da die Leistung so inkonsistent ist, ist es schwer zu sagen, ob Änderungen, die ich vornehme, eine Verbesserung darstellen oder nicht.
Joakim Hårsman
Haben Sie Code, den wir testen können? Das könnte uns sehr helfen.
PythonNut
1
Obwohl es nicht um Profilerstellung oder Mikrooptimierungen geht, an sich: Ich habe festgestellt, dass das Font-Lock-Studio- Paket ein weiteres hilfreiches Tool zum Verständnis der Font-Lock-Leistung ist. Dies kann genauso hilfreich sein wie jeder andere interaktive Stepping-Debugger. Möglicherweise stellen Sie fest, dass die Ausführungspfade nicht Ihren Erwartungen entsprechen und dass dies das Hauptproblem der Leistung ist.
Greg Hendershott
Danke für den Tipp zu Font-Lock-Studio, es ist großartig! Hilft zwar nicht mit Jit-Lock-Funktionen, aber sicher mit allem anderen.
Joakim Hårsman

Antworten:

8

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-registerwü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-registerProblem 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))))
Joakim Hårsman
quelle
Könnten Sie den verwendeten Code teilen? Ihre Lösung kann anderen helfen, die das Gleiche erreichen möchten.
Manuel Uberti
Ich habe eigentlich keinen bestimmten Code verwendet, sondern nur syntax-ppss genannt. Sie können den fraglichen Code hier überprüfen: bitbucket.org/harsman/dyalog-mode/src/… Look for dyalog-fontify-locals.
Joakim Hårsman
Ich denke, dyalog-fontify-locals-matchersollte sein my-font-lock-matcherund einer der endsollte sein limit. Eine wirklich interessante Entdeckung!
Lindydancer
@ Lindydancer: Ja, danke. Fest.
Joakim Hårsman
1
Betreff: gc-cons-thresholdWenn Sie nur mit internen Werten experimentieren, um die Startzeit zu verkürzen, empfehle ich emacs-startup-hook, diese Werte zu verwenden , um sie anschließend wiederherzustellen.
Phils