Skip to content

Optimize diff-hl--update#283

Merged
dgutov merged 1 commit into
dgutov:masterfrom
jamescherti:optimize-indirect-buffers
Jun 7, 2026
Merged

Optimize diff-hl--update#283
dgutov merged 1 commit into
dgutov:masterfrom
jamescherti:optimize-indirect-buffers

Conversation

@jamescherti

@jamescherti jamescherti commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

This pull request optimizes diff-hl--update.

@jamescherti jamescherti force-pushed the optimize-indirect-buffers branch 2 times, most recently from 92b5fa0 to f95dbef Compare June 5, 2026 15:27
@jamescherti

jamescherti commented Jun 5, 2026

Copy link
Copy Markdown
Contributor Author

This adds two optimizations during the buffer traversal.

First, (eq buf base) is checked before calling (buffer-base-buffer buf). This short-circuits evaluation to bypass the buffer-base-buffer call overhead.

Second, the boolean state of (or changes ref-changes) outside the loop. This prevents the Lisp interpreter from recalculating the same static condition for all active buffers.

@jamescherti jamescherti force-pushed the optimize-indirect-buffers branch from f95dbef to 8e0ef6d Compare June 5, 2026 16:46
@jamescherti jamescherti changed the title Ensure diff-hl-mode is bound and optimize diff-hl--update Optimize diff-hl--update Jun 5, 2026
@jamescherti jamescherti marked this pull request as draft June 5, 2026 16:58
@jamescherti jamescherti force-pushed the optimize-indirect-buffers branch from 8e0ef6d to 67eecb0 Compare June 5, 2026 17:02
@jamescherti jamescherti marked this pull request as ready for review June 5, 2026 17:10
@jamescherti jamescherti force-pushed the optimize-indirect-buffers branch from 67eecb0 to 8f484d7 Compare June 6, 2026 12:57
@dgutov

dgutov commented Jun 7, 2026

Copy link
Copy Markdown
Owner

Hi!

I like the (when ref-changes and (when changes improvements.

The other two seem negligible: considering we save the buffer-base-buffer call only once - when the buffer matches the original, but not for the other buffers; and we break the "target buffer" abstraction. Saving an or when the buffer already matched won't move the needle.

We could also drop the (buffer-live-p buf) check inside the loop because buffer-list returns only live ones. And that probably isn't going to change during our execution - we don't allow to run any timers or process filters during diff-hl--update-overlays or diff-hl--autohide-margin.

@jamescherti jamescherti force-pushed the optimize-indirect-buffers branch 2 times, most recently from e6d15fd to 0c9cdb3 Compare June 7, 2026 11:28
@jamescherti

Copy link
Copy Markdown
Contributor Author

That makes perfect sense. I have updated the pull request to preserve the diff-hl--target-buffer abstraction and dropped the redundant buffer-live-p checks inside the loop.

@jamescherti jamescherti force-pushed the optimize-indirect-buffers branch 2 times, most recently from 3366d5a to 7908fbe Compare June 7, 2026 11:40
@jamescherti

Copy link
Copy Markdown
Contributor Author

I also set inhibit-redisplay to t during the resolution callback to prevent the display engine from rendering intermediate UI states during asynchronous overlay updates. Because the function recreates a large number of overlays across multiple buffers, the Emacs display engine can waste CPU cycles recalculating display properties, margins, or fringe bitmaps before the buffer state is completely finalized.

@jamescherti jamescherti force-pushed the optimize-indirect-buffers branch from 7908fbe to 44d996b Compare June 7, 2026 11:44
@jamescherti jamescherti closed this Jun 7, 2026
@jamescherti jamescherti force-pushed the optimize-indirect-buffers branch from 44d996b to 81b7628 Compare June 7, 2026 12:28
@jamescherti jamescherti reopened this Jun 7, 2026
@dgutov

dgutov commented Jun 7, 2026

Copy link
Copy Markdown
Owner

I have updated the pull request to preserve the diff-hl--target-buffer abstraction and dropped the redundant buffer-live-p checks inside the loop.

Please drop the or optimization too, as I mentioned in the previous message.

Regarding inhibit-redisplay - do you have any measurements that show an improvement? It does help in some scenarios, but here I expect no redisplays to happen during that block's execution.

Redisplay happens at specific points of the event loop, not right after any change in a buffer.

@jamescherti jamescherti force-pushed the optimize-indirect-buffers branch 2 times, most recently from 9bee6d1 to 4449f16 Compare June 7, 2026 20:59
@jamescherti

Copy link
Copy Markdown
Contributor Author

I have removed the 'or' and inhibit-redisplay.

This adds optimizations to the buffer traversal and overlay application logic:

- Cache the boolean state of (or changes ref-changes) into a local
  variable 'has-changes' outside the loop to prevent the Lisp
  interpreter from recalculating it for all active buffers.
- Bind inhibit-redisplay to t during the resolution callback to prevent
  the display engine from rendering intermediate UI states during
  asynchronous overlay updates.
- Conditionally execute diff-hl--update-overlays only when 'changes' or
  'ref-changes' are non-nil, avoiding unnecessary function calls.
@jamescherti jamescherti force-pushed the optimize-indirect-buffers branch from 4449f16 to 8fe215f Compare June 7, 2026 21:04
@dgutov dgutov merged commit f8ffd77 into dgutov:master Jun 7, 2026
6 checks passed
@dgutov

dgutov commented Jun 7, 2026

Copy link
Copy Markdown
Owner

Thanks!

@jamescherti

Copy link
Copy Markdown
Contributor Author

You're very welcome!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants