Subject: bug#29889: 27.0.50; Slow visual selection

From: Eli Zaretskii <[email-masked]>
Date: Sun, 31 Dec 2017 20:43:47 +0200

> Date: Sun, 31 Dec 2017 17:37:52 +0200
> From: Eli Zaretskii <[email-masked]>
> Cc: [email-masked]
> 
> > After doing (setq gc-cons-threshold 1000000000), the issue doesn't
> > seem to happen. The cursor moved around freely except for one
> > interruption - maybe the GC kicked in then.
> 
> Oh, you are right: if I set garbage-collection-messages non-nil, I see
> a GC message each time I move the cursor.
> 
> So I guess my original theory was probably wrong, and the actual
> suspect is some code, yet to be discovered, that conses such large
> amounts of Lisp data.  I will look into it if no one beats me to it.

Long story short: set select-active-regions to 'only' or nil, and the
problem goes away.

Here's what happens: select-active-regions is now t by default, since
Emacs 24.1.  When that variable is t, every command, except those in
the list selection-inhibit-update-commands (a variable that is not
documented in any manual, btw), causes us to set the primary X
selection with the text in the active region.  Doing that invokes the
value of region-extract-function, which makes a string out of the
active region, which in this case is the entire buffer text.  For a
large buffer, such as vhdl.el, this conses a large string, thus
triggering GC _on_every_keystroke_.  And that _does_ make Emacs slow.

To add insult to injury, region-extract-function calls
buffer-substring--filter, which calls buffer-substring.  In a buffer
with a lot of text properties, such as the one that is fully
fontified, this involves copying the properties from the buffer to the
newly created string, most probably just to remove the properties
right after that (because the X selection doesn't need them).  Which
explains why a fully fontified buffer made things even more slow.

So how do we resolve this issue?  Should we set select-active-regions
to 'only' by default?  Should we arrange for region-extract-function
to call buffer-substring-no-properties instead, at least in this
specific use case?  Should we do both?  Something else?