Choosing the Right Line‑Number Display in Emacs: display‑line‑numbers vs linum‑mode vs nlinum‑mode
When working with large files or older Emacs builds, selecting a line‑number strategy can dramatically affect performance. This guide compares the built‑in display‑line‑numbers, the legacy linum‑mode, and the lightweight nlinum‑mode, then shows a practical init configuration and validation steps.
20 Nov 2025, 03:03 UTC

Decision Context
Emacs users often enable line numbers to improve navigation. Depending on the Emacs version, file size, and UI requirements, the choice of line‑number implementation can impact CPU usage, memory consumption, and visual fidelity. The three options considered here are:
- display-line-numbers – the modern overlay‑based system introduced in Emacs 26.
- linum-mode – the legacy line‑number mode that writes numbers as separate buffer lines.
- nlinum-mode – a lightweight third‑party mode that updates only on scroll.
Constraints
- Target Emacs versions: 25.x (no display-line-numbers support) and 26+ (full support).
- Typical use‑case: editing source files ranging from a few hundred lines to >10,000 lines.
- Performance: minimal CPU spikes during scrolling, low memory footprint.
- Visual quality: numbers should not interfere with code folding or overlays.
Option Comparison
| Feature | display-line-numbers | linum-mode | nlinum-mode |
|---|---|---|---|
| Availability | Emacs 26+ | All versions | Require package installation |
| Performance (large files) | Fast – uses overlay, only updates visible area | Slow – renders each line number as a separate line, high CPU and memory | Moderate – updates on scroll, slower than display-line-numbers for >10k lines |
| Memory Footprint | Minimal – overlay per line | High – one buffer line per code line | Low – similar to display-line-numbers but with occasional batch updates |
| Visual Quality | Consistent, aligns with UI, respects font-lock | May shift text, can cause horizontal scrolling flicker | Generally good, but numbers may misalign during rapid scrolling |
| Compatibility | Works with all major modes; respects window width changes | Can interfere with vertical scrolling in modes that use redisplay tricks | Depends on the implementation; usually safe but may conflict with custom overlays |
| Setup Complexity | Built‑in, simple global-display-line-numbers-mode | Built‑in, simple global-linum-mode | Package install, global-nlinum-mode call |
| Fallback for older Emacs | Not available – error if invoked | Always available | Requires manual package load; can be used as fallback |
Trade‑Offs
display-line-numbers is the most efficient for modern Emacs and large buffers. It integrates with the display engine, so scrolling is smooth and memory use stays low. The downside is that it is unavailable on Emacs 25, forcing users to switch to a different mode if they need backward compatibility.
linum-mode guarantees compatibility but at a steep cost. Each line number is a real buffer line, which means the buffer grows by the number of lines and every scroll operation forces the display engine to re‑render a large chunk of text. This can cause noticeable lag in 10,000+ line files.
nlinum-mode sits between the two. It updates numbers only when the view changes, reducing CPU churn compared to linum-mode, yet it still lags behind the overlay approach for very large files. It is useful when you need a lightweight alternative on older Emacs versions that still performs acceptably for moderate file sizes.
Implementation Example
Below is a concise init.el snippet that selects the best available strategy automatically. It enables display-line-numbers on Emacs 26+, falls back to nlinum-mode if the package is available, and finally uses linum-mode on older builds.
;; --- Line‑number strategy selector -------------------------------------------------
(defun my/enable-line-numbers ()
"Choose the most efficient line‑number mode available.
Emacs 26+ uses display-line-numbers.
If running Emacs 25, try nlinum-mode (if installed), otherwise linum-mode.
"
(cond
;; Modern Emacs – built‑in overlay system.
((>= emacs-major-version 26)
(setq display-line-numbers-type 'relative) ; or 't for absolute
(global-display-line-numbers-mode 1))
;; Emacs 25 – try nlinum first, then linum.
((>= emacs-major-version 25)
(if (require 'nlinum nil t)
(global-nlinum-mode 1)
(global-linum-mode 1)))
;; Very old Emacs – only linum is guaranteed.
(t
(global-linum-mode 1))))
;; Hook into after-init to activate.
(add-hook 'after-init-hook #'my/enable-line-numbers)
;; Optional: tweak the appearance of display-line-numbers.
(custom-set-variables
'(display-line-numbers-width 4) ; reserve 4 columns
'(display-line-numbers-widen t)) ; keep numbers in all windows
Replace display-line-numbers-type with 'absolute if you prefer absolute numbers. The display-line-numbers-width variable controls the column width; increasing it helps when you have long line numbers.
Validation Tips
To ensure the chosen mode behaves as expected, perform the following checks in a large file (e.g., 10,000 lines):
- Open the file and enable the mode.
- Run
M-x profiler-start <buffer>to begin profiling. - Scroll up and down several times.
- Run
M-x profiler-reportand look forredisplayanddisplay-line-numbers(orlinum) entries. Lower CPU time indicates better performance. - Optionally use
M-x benchmark-runwith a simple loop:
The reported time per iteration should be noticeably smaller for(benchmark-run 1000 (scroll-up-command))display-line-numbersthan forlinum-mode. - Check memory usage via
M-x memory-reportor external tools; the buffer size should not grow by the number of lines when usingdisplay-line-numbers.
When using the fallback path on Emacs 25, verify that nlinum-mode is installed (e.g., via MELPA) and that scrolling remains smooth. If performance is unacceptable, consider upgrading to Emacs 26+.
Conclusion
For most users on Emacs 26 or newer, display-line-numbers is the clear choice: it is fast, memory‑efficient, and visually consistent. On older Emacs builds, nlinum-mode offers a lightweight alternative, while linum-mode should be reserved for legacy environments where no other options are available.
By automating the selection in your init file and validating with profiling, you can ensure a smooth editing experience across a wide range of file sizes and Emacs versions.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.