Files
emacs-config/lisp/init-performance.el
2025-09-09 16:08:15 +02:00

206 lines
7.3 KiB
EmacsLisp

;;; init-performance.el --- Performance optimizations and fixes -*- lexical-binding: t -*-
;;; Commentary:
;;; Comprehensive performance optimizations to prevent UI freezing, lag, and other issues
;;; Code:
;;;; Garbage Collection Optimizations
;; Increase garbage collection threshold during startup
(setq gc-cons-threshold (* 100 1024 1024)) ; 100MB
(setq gc-cons-percentage 0.6)
;; Reset after startup
(add-hook 'emacs-startup-hook
(lambda ()
(setq gc-cons-threshold (* 16 1024 1024)) ; 16MB
(setq gc-cons-percentage 0.1)))
;;;; File Watching and Auto-revert Optimizations
(setq auto-revert-interval 5) ; Check every 5 seconds instead of 1
(setq auto-revert-use-notify t) ; Use file system notifications
(setq auto-revert-avoid-polling t) ; Don't poll, use notifications
(setq global-auto-revert-non-file-buffers nil) ; Don't auto-revert non-file buffers
;;;; Display and Rendering Optimizations
(setq idle-update-delay 2.0) ; Default is 0.5
(setq redisplay-dont-pause t) ; Never pause redisplay
(setq fast-but-imprecise-scrolling t) ; Faster scrolling
(setq inhibit-compacting-font-caches t) ; Don't compact font caches during GC
;; Font-lock optimizations
(setq jit-lock-defer-time 0.05) ; Slightly defer font-locking
(setq jit-lock-stealth-time 5) ; Wait 5 seconds before stealth fontification
(setq jit-lock-chunk-size 1000) ; Smaller chunks
(setq jit-lock-stealth-load 20) ; Don't fontify when load is high
;; Disable bidirectional text rendering for performance
(setq-default bidi-display-reordering nil)
(setq-default bidi-paragraph-direction 'left-to-right)
;; Optimize long line handling
(setq-default truncate-lines t)
(setq line-move-visual nil)
;;;; Memory and Process Optimizations
(setq undo-limit 80000) ; Default is 160000
(setq undo-strong-limit 120000) ; Default is 240000
(setq undo-outer-limit 12000000) ; Default is 24000000
(setq read-process-output-max (* 1024 1024)) ; 1MB, default is 4096
;;;; X11 Specific Optimizations (for no-toolkit builds)
(when (and (display-graphic-p)
(not (memq window-system '(ns mac w32))))
;; More aggressive redrawing for X11
(setq idle-update-delay 0.1) ; Faster idle updates
(setq redisplay-skip-fontification-on-input nil)) ; Don't skip font-lock
;;;; Timer Management Functions
(defun clear-duplicate-idle-timers ()
"Remove duplicate idle timers that may be causing performance issues."
(let ((seen-timers '()))
(dolist (timer timer-idle-list)
(let ((timer-func (timer--function timer)))
(if (member timer-func seen-timers)
(cancel-timer timer)
(push timer-func seen-timers))))))
(defun disable-qml-timers ()
"Disable QML idle timers."
(dolist (timer timer-idle-list)
(when (and (timer--function timer)
(eq (timer--function timer) 'qml-timer-handler))
(cancel-timer timer))))
;; Run timer cleanup on load
(clear-duplicate-idle-timers)
(disable-qml-timers)
;;;; Mode-specific Performance Fixes
;; Disable DAP mode if it's somehow enabled (causes major lag)
(when (boundp 'dap-mode)
(dap-mode -1))
(when (boundp 'dap-ui-mode)
(dap-ui-mode -1))
(when (boundp 'dap-auto-configure-mode)
(dap-auto-configure-mode -1))
;; Disable LSP-UI doc if causing issues
(when (boundp 'lsp-ui-doc-mode)
(setq lsp-ui-doc-enable nil))
;; Prevent QML timers from being created
(with-eval-after-load 'qml-mode
(remove-hook 'qml-mode-hook 'qml-start-timer-handler)
(fset 'qml-timer-handler 'ignore)
(fset 'qml-start-timer-handler 'ignore))
;; Prevent LSP from activating in QML files
(with-eval-after-load 'lsp-mode
;; Remove QML mode from LSP's activation list
(setq lsp--major-modes-for-activate
(delete 'qml-mode lsp--major-modes-for-activate))
;; Advise lsp-deferred to skip QML files
(defadvice lsp-deferred (around no-lsp-for-qml activate)
"Prevent LSP from starting in QML mode."
(unless (eq major-mode 'qml-mode)
ad-do-it)))
;;;; Large File Handling
(defun my-large-file-hook ()
"Disable expensive features in large files."
(when (> (buffer-size) (* 1024 1024)) ; Files larger than 1MB
(setq-local line-number-mode nil)
(setq-local column-number-mode nil)
(setq-local show-paren-mode nil)
(setq-local font-lock-mode nil)
(setq-local bidi-display-reordering nil)))
(defun check-large-file-performance ()
"Disable expensive features in large files (512KB threshold)."
(when (> (buffer-size) (* 512 1024)) ; Files larger than 512KB
(when (bound-and-true-p rainbow-delimiters-mode)
(rainbow-delimiters-mode -1))
(when (bound-and-true-p diff-hl-mode)
(diff-hl-mode -1))
(when (bound-and-true-p undo-tree-mode)
(undo-tree-mode -1))))
(add-hook 'find-file-hook 'my-large-file-hook)
(add-hook 'find-file-hook 'check-large-file-performance)
;; Prevent timer accumulation when killing buffers
(add-hook 'kill-buffer-hook
(lambda ()
(when (derived-mode-p 'qml-mode)
(disable-qml-timers))))
;;;; Manual Performance Control Functions
(defun force-redraw ()
"Force a complete redraw of the frame."
(interactive)
(redraw-frame))
(defun force-redraw-all ()
"Force redraw of all frames and windows."
(interactive)
(dolist (frame (frame-list))
(redraw-frame frame))
(redisplay t))
(defun fix-performance-now ()
"Fix all known performance issues immediately."
(interactive)
;; Disable DAP
(when (boundp 'dap-mode) (dap-mode -1))
(when (boundp 'dap-ui-mode) (dap-ui-mode -1))
(when (boundp 'dap-auto-configure-mode) (dap-auto-configure-mode -1))
;; Clear timers
(clear-duplicate-idle-timers)
(disable-qml-timers)
;; Force garbage collection
(garbage-collect)
(message "Performance fixes applied!"))
(defun diagnose-performance ()
"Show information about potential performance issues."
(interactive)
(with-current-buffer (get-buffer-create "*Performance Diagnostic*")
(erase-buffer)
(insert "=== Emacs Performance Diagnostic ===\n\n")
(insert (format "Garbage Collection Threshold: %s\n" gc-cons-threshold))
(insert (format "Garbage Collection Percentage: %s\n" gc-cons-percentage))
(insert (format "Auto-revert interval: %s\n" auto-revert-interval))
(insert (format "Number of buffers: %s\n" (length (buffer-list))))
(insert (format "Active minor modes: %s\n"
(mapconcat 'symbol-name
(delq nil (mapcar (lambda (m) (and (boundp m) (symbol-value m) m))
minor-mode-list))
", ")))
(insert "\n=== Active Timers ===\n")
(dolist (timer timer-list)
(insert (format "%s\n" timer)))
(insert "\n=== Idle Timers ===\n")
(dolist (timer timer-idle-list)
(insert (format "%s\n" timer)))
(switch-to-buffer (current-buffer))))
;;;; Keybindings for Performance Control
(global-set-key (kbd "C-c r r") 'force-redraw)
(global-set-key (kbd "C-c r a") 'force-redraw-all)
(global-set-key (kbd "C-c p f") 'fix-performance-now)
(global-set-key (kbd "C-c p d") 'diagnose-performance)
;;;; Window Configuration Hook
(add-hook 'window-configuration-change-hook
(lambda ()
(when (and (display-graphic-p)
(not (memq window-system '(ns mac w32))))
(redisplay))))
(provide 'init-performance)
;;; init-performance.el ends here