nschum / highlight-symbol.el

Emacs: automatic and manual symbol highlighting
http://nschum.de/src/emacs/highlight-symbol/
274 stars 41 forks source link

performance issue #26

Open Pitometsu opened 9 years ago

Pitometsu commented 9 years ago

With enable highlight-symbol-mode have very bad performance issues on big (~500 lines) files... Cursor freezing all the time!

md1023 commented 8 years ago

6K lines don't load fast and nav-mode works a bit slow. Humbly hoping for improvements :)

Nephyrin commented 8 years ago

highlight-symbol-mode seems to force fontification repeatedly, rather than marking things for lazy fontification. This means large files will stutter like crazy as the whole document is re-highlighted repeatedly. It's a bummer, as this mode is otherwise super useful.

Nephyrin commented 8 years ago

So I looked into this, it seems like this should be solved on emacs >= 25:

(defun highlight-symbol-flush ()
  (if (fboundp 'font-lock-flush)
      (font-lock-flush)
    ;; Emacs < 25
    (with-no-warnings
      (font-lock-fontify-buffer))))

font-lock-flush should passively re-fontify things, while font-lock-fontify-buffer would be the orbital performance nuke. I was using emacs-25 when I was seeing issues, but I'll re-enable things and see if I can track down what's going wrong. It might need to be more specific with what regions it dirties.

stakemori commented 8 years ago

I am using Emacs 25, but I still have this issue, especially in a large nested C code.

I don't think use of font-lock.el is appropriate, because font-lock.el is intended for much more complicated tasks than highlight-symbol does. So I re-defined highlight-symbol-add-symbol-with-face and highlight-symbol-remove-symbol by using overlays.

    (defun highlight-symbol-add-symbol-with-face (symbol face)
      (save-excursion
        (goto-char (point-min))
        (while (re-search-forward symbol nil t)
          (let ((ov (make-overlay (match-beginning 0)
                                  (match-end 0))))
            (overlay-put ov 'highlight-symbol t)
            (overlay-put ov 'face face)))))

    (defun highlight-symbol-remove-symbol (_symbol)
      (dolist (ov (overlays-in (point-min) (point-max)))
        (when (overlay-get ov 'highlight-symbol)
          (delete-overlay ov))))

Then the performance improved. This implementation can be improved more, because you should highlight symbols only in the range from (window-start) to (window-end).