From 3fd28987f7f1e4da226d650166cc64e71e30e645 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Sat, 20 Jun 2026 23:26:44 -0400 Subject: perf: re-enable native-comp JIT and hand GC to gcmh early-init.el disabled JIT native compilation with (setq native-comp-deferred-compilation nil), the obsolete alias of native-comp-jit-compilation. Despite the comment, setting it nil turns JIT off entirely rather than making it synchronous. Most modules then ran interpreted for the daemon's lifetime, and the native-comp-speed/jobs settings in system-defaults.el were dead. The "Selecting deleted buffer" async race that prompted the disable was an Emacs 28/29 issue. This is 30.2. I re-enabled it with native-comp-jit-compilation t and silent async warnings. GC was pinned at the stock 800KB: early-init restored it post-startup and the minibuffer setup/exit hooks bounced back to it. That's Emacs's bare-editor default, far too low for 184 packages, so GC pauses fired often during completion, agenda, and LSP/AI work. I replaced both hand-rolled mechanisms with gcmh, which keeps the threshold at 1GB during activity and collects on idle. Verified a clean full launch in a throwaway daemon (JIT on, gcmh active, no backtrace) and gcmh's threshold cycle in batch. --- modules/gcmh-config.el | 30 ++++++++++++++++++++++++++++++ modules/system-defaults.el | 19 +++++++------------ 2 files changed, 37 insertions(+), 12 deletions(-) create mode 100644 modules/gcmh-config.el (limited to 'modules') diff --git a/modules/gcmh-config.el b/modules/gcmh-config.el new file mode 100644 index 000000000..beceb1a01 --- /dev/null +++ b/modules/gcmh-config.el @@ -0,0 +1,30 @@ +;;; gcmh-config.el --- Garbage collection strategy via gcmh -*- lexical-binding: t -*- + +;;; Commentary: +;; gcmh (the Garbage Collector Magic Hack) owns `gc-cons-threshold' for the +;; session. It keeps the threshold very high while you are active so GC never +;; pauses mid-edit, then drops it and collects on idle, when a pause is +;; invisible. This replaces the old hand-rolled scheme -- a stock-800KB restore +;; in early-init.el plus a minibuffer setup/exit bump -- which pinned GC at +;; 800000 (Emacs's bare-editor default), far too low for a config this size and +;; the cause of frequent GC pauses during completion, agenda builds, and LSP/AI +;; activity. +;; +;; Kept in its own module, not system-defaults.el: that module is pre-loaded by +;; the comp-errors test harness, which has no package system, so an `:ensure' +;; package there errors at load time. early-init.el bumps the threshold to +;; `most-positive-fixnum' for startup and deliberately does not restore it; +;; `gcmh-mode' takes ownership from here on. + +;;; Code: + +(use-package gcmh + :ensure t + :demand t + :config + (setq gcmh-idle-delay 'auto ; scale the idle GC delay to GC cost + gcmh-high-cons-threshold (* 1 1024 1024 1024)) ; 1 GB during activity + (gcmh-mode 1)) + +(provide 'gcmh-config) +;;; gcmh-config.el ends here diff --git a/modules/system-defaults.el b/modules/system-defaults.el index 0062a82cf..6d9c811a6 100644 --- a/modules/system-defaults.el +++ b/modules/system-defaults.el @@ -212,18 +212,13 @@ appears only once per session." (setq custom-safe-themes t) ;; treat all themes as safe (stop asking) (setq server-client-instructions nil) ;; I already know what to do when done with the frame -;; ------------------ Reduce Garbage Collections In Minibuffer ----------------- - -(defun cj/minibuffer-setup-hook () - "Hook to prevent garbage collection while user's in minibuffer." - (setq gc-cons-threshold most-positive-fixnum)) - -(defun cj/minibuffer-exit-hook () - "Hook to trigger garbage collection when exiting minibuffer." - (setq gc-cons-threshold 800000)) - -(add-hook 'minibuffer-setup-hook #'cj/minibuffer-setup-hook) -(add-hook 'minibuffer-exit-hook #'cj/minibuffer-exit-hook) +;; ----------------------------- Garbage Collection ---------------------------- +;; GC is managed by gcmh in modules/gcmh-config.el: it keeps gc-cons-threshold +;; high during activity and collects on idle, replacing the old stock-800KB +;; scheme (an early-init restore plus a minibuffer setup/exit bump). gcmh lives +;; in its own module rather than here because system-defaults.el is pre-loaded +;; by the comp-errors test harness, which has no package system -- an `:ensure' +;; package loaded here would error at load time and break those tests. ;; ----------------------------- Bookmark Settings ----------------------------- -- cgit v1.2.3