Debounce search buffer updates during feed fetches#558
Open
benthamite wants to merge 1 commit intoskeeto:masterfrom
Open
Debounce search buffer updates during feed fetches#558benthamite wants to merge 1 commit intoskeeto:masterfrom
benthamite wants to merge 1 commit intoskeeto:masterfrom
Conversation
When elfeed fetches feeds, each completion callback triggers `elfeed-search-update' via `elfeed-update-hooks'. The URL string passed by `run-hook-with-args' was interpreted as a truthy `force' argument, causing every callback to force a full buffer redraw (DB scan + erase + re-render all entries). With hundreds of feeds this produced hundreds of forced redraws back-to-back, freezing Emacs. Split `elfeed-search-update' into a dispatcher: forced calls (interactive `g', filter changes, mode init) redraw immediately; non-forced calls schedule a trailing-edge debounce timer (`elfeed-search-update-delay', default 1.5s). A new `elfeed-search--update-debounced' wrapper on `elfeed-update-hooks' discards the URL argument so callbacks enter the debounce path.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
elfeed-search-updateso that rapid feed completions coalesce into a single redraw instead of one per feedelfeed-update-hookspassed the feed URL as theforceparameter, bypassing the staleness guard and forcing a full redraw on every callbackelfeed-search-update-delay(default 1.5s)Closes #293. Also addresses #317 and #474.
Problem
When
elfeed-updatefetches feeds, each completion runs:elfeed-search-updateis on this hook and receives the URL string as its optionalforceargument. Since any string is truthy, every feed completion triggers a forced full redraw of the search buffer (full DB scan viawith-elfeed-db-visit,erase-buffer, re-render all matching entries). With N feeds, this produces N forced full redraws fired back-to-back asrun-at-time 0timer events, each blocking the main thread.With ~300 feeds, this freezes Emacs intermittently for 30-60 seconds.
Fix
All changes are in
elfeed-search.el:Debounce non-forced calls.
elfeed-search-updatenow dispatches: whenforceis non-nil it redraws immediately (preserving existing behavior for interactiveg, filter changes, mode init); whenforceis nil it schedules a trailing-edge debounce timer. If another call arrives before the timer fires, it resets. This coalesces hundreds of rapid callbacks into a handful of redraws.Fix the argument mismatch. A new wrapper
elfeed-search--update-debounceddiscards the URL argument from the hook and callselfeed-search-updatewith no arguments, entering the debounce path instead of the forced path. This replaceselfeed-search-updateonelfeed-update-hooks.Timer cleanup. The debounce timer is canceled in
elfeed-search--unloadwhen the search buffer is killed.Result
With 317 feeds: ~5-10 redraws instead of 317+. Emacs remains fully responsive throughout the update. Interactive refresh (
g), filter changes, and live filtering are unaffected.Backward compatibility
elfeed-update-hookscontract unchanged: hook still fires once per feed completionelfeed-search-update-hookunchanged: still fires after every actual buffer updateelfeed-search-updatestill accepts optionalforcewith same semanticselfeed-search-update--forcestill forces immediate updateelfeed-search-print-entry-functionimplementations are unaffectedTest plan
Gin search buffer: feeds fetch without freezing, buffer updates after completions settlegin search buffer: immediate forced refresh (no debounce)s): still updates immediately as you typeelfeed-search-set-filter: immediate update