bug#81623: 32.0.50; Long-line optimization severely slows redisplay of invisible newlines
Eli Zaretskii <[email protected]>
| Newsgroups | gmane.emacs.bugs |
|---|---|
| Message-ID | <[email protected]> |
tags 81623 notabug thanks > From: Scott Guest <[email protected]> > Date: Fri, 14 Aug 2026 22:52:17 -0700 > > > Run the following under `emacs -Q -l`: > > ```elisp > (defun reproduce (long-line-length) > (let ((buffer (generate-new-buffer " *redisplay bug*")) body-begin start) > (with-current-buffer buffer > ;; This line is before, and outside, the invisible region below. > (insert (make-string long-line-length ?x) "\n") > ;; U+03BB makes byte and character positions differ. > (insert (string #x03bb) " visible header\n") > (setq body-begin (point)) > ;; START will be inside a logical line, after 40,000 hidden newlines. > (insert (make-string 40000 ?\n) "x") > (setq start (point)) > (insert "\n") > (put-text-property body-begin (point-max) 'invisible t)) > (switch-to-buffer buffer) > (goto-char start) > (set-window-start nil start t) > (force-window-update) > (let ((time (current-time))) > (redisplay t) > (princ (format "long line %d; optimization %S; redisplay %.3fs\n" > long-line-length (long-line-optimizations-p) > (float-time (time-since time))) > #'external-debugging-output)))) > > (reproduce 49999) > (reproduce 50000) > (kill-emacs) > ``` > > Typical output: > > ```text > long line 49999; optimization nil; redisplay 0.126s > long line 50000; optimization t; redisplay 2.101s > ``` > > Crossing the default `long-line-threshold` by one character makes > redisplay approximately 17 times slower in this run. With larger inputs > where I've encountered this in the wild, the slowdown is egregious > enough that it's indistinguishable from a hang. > > Tested with GNU Emacs 32.0.50 from master, commit > `7861c306427e7488a623d296e1efb05509cc7cc6`, in a graphical session. Thank you for your report. The default value of long-line-threshold is just that: the default. In particular, it was defined for cases where buffer text is not concealed by the invisible property, at least not significant portions of it. If in your use case this assumption is not true, simply enlarge the threshold value, or even make it nil. That's why we exposed the value to Lisp in the first place. IOW, the default value of the threshold is for when the long lines are actually visible on display. I don't see a bug here, just a feature that needs to be used more wisely in specific situations.