James Cherti: Configuring the Emacs UI for better perceived responsiveness and latency

Wait 5 sec.

When I first changed from Vim to Emacs a few years ago, the editor's user interface felt sluggish. I quickly learned that the Emacs UI itself is not slow, rather, its default settings can make it feel that way. (Enhancing Emacs defaults is what drove me to develop minimal-emacs.d) To restore the instant feedback loop I was accustomed to, I needed to tune the editor.The configurations below are the result of my tuning process to enhance the perceived Emacs UI responsiveness and latency. These settings are best treated as independent experiments. I recommend testing these adjustments iteratively.Show-paren delayThe show-paren-delay controls how long Emacs waits, after becoming idle, before highlighting a matching parenthesis when show-paren-mode is active.(setq show-paren-delay 0.05)A shorter delay makes delimiter matching appear closer to the point at which the cursor reaches the parenthesis. This is pleasant in Lisp buffers, where matching delimiters carry a large amount of structural information. (The setting does not make parenthesis matching itself faster. It only changes when the visual result is displayed.)A very small value can make the highlight appear frequently while point is moving quickly through source code.FontificationFont lock decoration levelThe font-lock-maximum-decoration variable controls how much Font Lock highlighting major modes request.(setq font-lock-maximum-decoration '((t . 1)))Level 1 is a relatively minimal level of decoration. Higher levels generally add more syntax details.The tradeoff is reduced semantic information in the display. Functions, declarations, built-in names, and other constructs that appear at higher decoration levels may no longer receive their usual faces. (Reducing decoration lowers the amount of regular-expression and syntax analysis performed by modes that support Font Lock levels.)This setting affects traditional Font Lock. For major modes that use Tree-sitter, use treesit-font-lock-level. Its default is 3. Level 1 usually fontifies comments and function names in function definitions. Level 2 additionally fontifies keywords, strings, and data types. Lowering the level can reduce the amount of fontification performed:(setq treesit-font-lock-level 2)Font Cache CompactionThe inhibit-compacting-font-caches variable prevents Emacs from compacting its font caches:(setq inhibit-compacting-font-caches t)This variable can improve display performance with large fonts by preventing font-cache compaction, at the cost of increased memory usage.Skipping Some Fontification While Input Is PendingThe redisplay-skip-fontification-on-input variable allows Emacs to skip some fontification when input is waiting:(setq redisplay-skip-fontification-on-input t)When input is pending, Emacs can skip fontification. This can make scrolling smoother by avoiding fontification work while Emacs is trying to keep up with incoming input. It does not permanently disable syntax highlighting. The affected text can be fontified on a later redisplay.ScrollingScrolling can become slow when Emacs displays unfontified text. Setting fast-but-imprecise-scrolling to t prevents Emacs from becoming unresponsive when you move rapidly through buffers:(setq fast-but-imprecise-scrolling t)The main tradeoff is that scrolling can become visually imprecise. However, for typical coding tasks using a standard monospaced font, line heights remain consistent, meaning you will likely never experience this imprecision at all.Even in modes that do use variable font sizes, the visual jump is minor and temporary. Once you stop scrolling and the input queue clears, Emacs finishes fontifying the visible text and corrects the layout, ensuring your final view is accurate.Which-keyThe which-key-idle-delay variable controls how long which-key-mode waits after a prefix key is entered before displaying the available bindings:(setq which-key-idle-delay 0.5)Reducing the delay makes key discovery appear sooner, but it also increases the likelihood that a popup will appear during an ordinary key sequence. (For experienced users with memorized prefixes, a longer delay can reduce visual interruptions.)TooltipTooltip DelayThe tooltip-delay variable determines how long Emacs tooltip-mode waits before displaying the first tooltip after the pointer rests over an item that provides tooltip information:(setq tooltip-delay 0.3)A shorter delay can also make accidental hover events more intrusive. (For keyboard-centric workflows, increasing the delay or disabling tooltips entirely may be preferable to making them appear more quickly.)Tooltip Short DelayThe tooltip-short-delay variable controls the delay before showing a subsequent tooltip after a tooltip has already been displayed:(setq tooltip-short-delay 0.08)This setting is mainly about interaction latency rather than Emacs's general execution speed. Very short values can make mouse movement produce a succession of tooltip updates.Third-party package: Evil modeThe evil-ex-hl-update-delay variable controls the amount of idle time before Evil updates search highlighting:(setq evil-ex-hl-update-delay 0.01)Lowering it to 0.01 seconds makes highlighting react a little sooner while editing an Ex search pattern. The variable does not make regular-expression searches faster. It reduces the delay before Evil starts the next highlight update.Icomplete Compute DelayThe icomplete-compute-delay variable controls how long icomplete waits before computing completions after minibuffer input changes:(setq icomplete-compute-delay 0.01)A value of 0.01 seconds makes icomplete react almost immediately, which reduces the grace period that allows another keystroke to arrive before computation begins.Note: For large or computationally expensive completion tables, reducing this delay can instead cause more work to be performed during typing. The optimal value depends heavily on the completion source.Third-party package: CorfuThe corfu-auto-delay variable specifies how long Corfu waits before displaying automatic completion after its auto-completion conditions are met:(setq corfu-auto-delay 0.1)Lowering this delay speeds up when the completion popup appears, but it can introduce interface lag.The package documentation warns that overly aggressive values can increase the amount of work performed during typing. If completion computation is expensive, querying it more frequently can make typing less responsive.Test different values incrementally until you find the right balance for your configuration.Emacs on MS WindowsEnhance performance on Windows by fixing file I/O and process bottlenecks:(when (memq system-type '(windows-nt cygwin ms-dos)) (setq w32-pipe-read-delay 0 ; Faster IPC w32-get-true-file-attributes nil ; Decrease file IO workload w32-pipe-buffer-size (* 128 1024))) ; Read more at a timeThis reduces latency on Windows when working with language servers (LSP), asynchronous searches, and version control.PGTK Frame Event TimeoutThe pgtk-wait-for-event-timeout variable is for Emacs builds using the PGTK toolkit. It specifies how long Emacs may wait for graphical events after changes that affect graphical-interface state.(when (boundp 'pgtk-wait-for-event-timeout) (setq pgtk-wait-for-event-timeout 0.001))Reducing the timeout reduces the maximum time Emacs waits for the relevant GTK event, which can reduce latency for operations that show or hide frames.This setting is specific to PGTK, so the boundp guard prevents errors on builds that do not define the variable. A very small timeout reduces the amount of time Emacs waits for the event to arrive.Input Latency on Emacs GTKIf you experience keyboard input latency in Emacs GTK builds, it is frequently caused by the GTK input method interface.For users who do not rely on GTK input methods (e.g., If you primarily type in standard ASCII/English), the following UNIX/Linux environment variable can be tested:export GTK_IM_MODULE=noneThis disables the GTK input method module for the Emacs process and can avoid latency caused by problematic GTK input methods.Emacs built with GTK lags in its response to keyboard input: This can happen when input methods are used. It happens because Emacs behaves in an unconventional way with respect to GTK input methods: it registers to receive keyboard input as unprocessed key events with metadata (as opposed to receiving them as text strings). Most GTK programs use the latter approach, so some modern input methods have bugs and misbehave when faced with the way Emacs does it. A workaround is to set GTK_IM_MODULE=none in the environment, or maybe find a different input method without these problems.For PGTK builds, you can disable the input method context directly in Elisp:(setq pgtk-use-im-context nil)Window Manager and Frame Operation DelaysCertain window managers fail to send expected confirmation events back to Emacs, which triggers multi-second pauses during interface adjustments.If changing fonts causes a pause of up to five seconds, Emacs is waiting for a ConfigureNotify event from the window manager that never arrives. Try preventing Emacs from waiting for the window manager by using:;; Apply to all future frames, including emacsclient frames(add-to-list 'default-frame-alist '(wait-for-wm . nil));; Apply immediately to the startup frame if a GUI frame exists(when (display-graphic-p) (modify-frame-parameters nil '((wait-for-wm . nil))))If creating or resizing frames is slow, try:(setq frame-resize-pixelwise nil)If Emacs is slow on X forwarded displays, querying the pointer location can be the bottleneck. Try the following:(setq mouse-highlight nil)Emacs is slow to exit in X, it could be caused by clipboard timeouts. Emacs communicates with external clipboard managers during selection changes and session shutdown. If the external manager fails to respond promptly, Emacs blocks interactive execution while waiting for a response. Try the following:(setq x-select-enable-clipboard-manager nil)(setq x-selection-timeout 100)If selecting text with the mouse cause lag because external utilities poll selection changes continuously:(setq select-active-regions nil)ConclusionEmacs responsiveness is influenced by several components, including redisplay, fontification, completion, and graphical event handling. The settings above target specific sources of perceived latency and are best evaluated individually.And you? Which settings have made the biggest difference in your setup?Related posts:Copy-paste without Emacs org-mode or markdown-mode Formatting Bleeding Into Other BuffersConfiguring Emacs Eglot for Better Performance and LatencyEmacs startup - Why setq beats setopt, customize-set-variable, and use-package :custom?Measuring Emacs startup time more accurately than the built-in emacs-init-timeWhy Emacs Consult async searches feel slow and how to speed them up? (consult-fd, consult-find, consult-grep, consult-ripgrep...)Fixing slow scrolling in Emacs display-line-numbers-modeWhy your Emacs terminal is slow and how to fix It (vterm, eat, ghostel, term, and ansi-term)Optimizing Emacs startup - Guide to deferred package loading with use-packageA Technical Guide to Compiling Emacs for Performance on Linux and Unix systemsThe compile-angel Emacs package: Byte-compile and Native-compile Emacs Lisp libraries Automaticallyultisnips-mode.el - An Emacs major mode for editing Ultisnips snippet files (*.snippets files)easysession.el: Easily persist and restore Emacs sessions (windows, tab-bar, file buffers, scratch, Dired, narrowing, indirect buffers/clones, Magit buffers...); a robust desktop.el replacementEglot for Python Development in Emacs: Integrating python-lsp-server (pylsp) with Linters and FormattersBest Emacs Packages for Efficient Software Development and Text Editingquick-fasd.el - Integrate Fasd for fast file and directory navigation in Emacsbuffer-guardian.el - Automatically Save Emacs Buffers Without Manual Intervention (When Buffers Lose Focus, Regularly, or After Emacs is Idle)Enabling Emacs Native Compilation and Dynamically Adjusting the Number of Elisp Files Compiled in ParallelFixing Emacs Dired defaults - Settings for better file managementSecuring Emacs .dir-locals.el and local variablesEmacs Evil Mode: Disabling the automatic removal of spaces after leaving Insert mode