From 07454c47a62d9450f194dc0177a3a5b10846195b Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jo=C3=A3o=20T=C3=A1vora?= Date: Tue, 5 Sep 2023 17:20:25 +0100 Subject: [PATCH] Flymake: speed up mode-line display with simple cache When scrolling heavily (perhaps holding down C-n), the function 'flymake-mode-line-counter' showed very prominently in the memory and CPU profiles. Using a cache here was trivial, if not particularly pretty. The function all but disappears from the profiles afterwards. * lisp/progmodes/flymake.el (flymake--mode-line-counter-cache): New variable. (flymake--publish-diagnostics): Flush cache aggressively. (flymake-mode-line-error-counter): Adjust. (flymake--mode-line-counter-1): New helper from earlier flymake--mode-line-counter. (flymake--mode-line-counter): Use cache. --- lisp/progmodes/flymake.el | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/lisp/progmodes/flymake.el b/lisp/progmodes/flymake.el index b4c0e4db6ac..9695ee3d849 100644 --- a/lisp/progmodes/flymake.el +++ b/lisp/progmodes/flymake.el @@ -965,6 +965,9 @@ report applies to that region." (defvar-local flymake-mode nil) +(defvar-local flymake--mode-line-counter-cache nil + "A cache used in `flymake-mode-line-counters'.") + (cl-defun flymake--publish-diagnostics (diags &key backend state region) "Helper for `flymake--handle-report'. Publish DIAGS, which contain diagnostics for the current buffer @@ -1025,7 +1028,9 @@ and other buffers." (setf (flymake--diag-locus d) (buffer-file-name)))) (cl-assert (stringp (flymake--diag-locus d))) (push d (gethash (flymake--diag-locus d) - (flymake--state-foreign-diags state)))))))) + (flymake--state-foreign-diags state)))))) + ;; Finally, flush some caches + (setq flymake--mode-line-counter-cache nil))) (defun flymake-make-report-fn (backend &optional token) "Make a suitable anonymous report function for BACKEND. @@ -1501,7 +1506,7 @@ The counters are only placed if some Flymake backend initialized correctly.") (defvar flymake-mode-line-error-counter - `(:eval (flymake--mode-line-counter :error t))) + `(:eval (flymake--mode-line-counter :error))) (defvar flymake-mode-line-warning-counter `(:eval (flymake--mode-line-counter :warning))) (defvar flymake-mode-line-note-counter @@ -1598,9 +1603,8 @@ correctly.") #'flymake--mode-line-counter-scroll-next) map)) -(defun flymake--mode-line-counter (type &optional no-space) - "Compute number of diagnostics in buffer with TYPE's severity. -TYPE is usually keyword `:error', `:warning' or `:note'." +(defun flymake--mode-line-counter-1 (type) + "Helper for `flymake--mode-line-counter'." (let ((count 0) (face (flymake--lookup-type-property type 'mode-line-face @@ -1617,7 +1621,7 @@ TYPE is usually keyword `:error', `:warning' or `:note'." (warning-numeric-level flymake-suppress-zero-counters))) (t t))) - `(,(if no-space "" '(:propertize " ")) + `(,(if (eq type :error) "" '(:propertize " ")) (:propertize ,(format "%d" count) face ,face @@ -1631,6 +1635,15 @@ TYPE is usually keyword `:error', `:warning' or `:note'." flymake--diagnostic-type ,type keymap ,flymake--mode-line-counter-map))))) +(defun flymake--mode-line-counter (type) + "Compute number of diagnostics in buffer with TYPE's severity. +TYPE is usually keyword `:error', `:warning' or `:note'." + (let ((probe (alist-get type flymake--mode-line-counter-cache 'none))) + (if (eq probe 'none) + (setf (alist-get type flymake--mode-line-counter-cache) + (flymake--mode-line-counter-1 type)) + probe))) + ;;; Per-buffer diagnostic listing (defvar-local flymake--diagnostics-buffer-source nil) -- 2.39.2