Package: emacs;
Reported by: Anders Lindgren <andlind <at> gmail.com>
Date: Fri, 13 Dec 2013 14:35:03 UTC
Severity: normal
Found in version 24.3.50
Done: Eli Zaretskii <eliz <at> gnu.org>
Bug is archived. No further changes may be made.
To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 16129 in the body.
You can then email your comments to 16129 AT debbugs.gnu.org in the normal way.
Toggle the display of automated, internal messages from the tracker.
View this report as an mbox folder, status mbox, maintainer mbox
bug-gnu-emacs <at> gnu.org
:bug#16129
; Package emacs
.
(Fri, 13 Dec 2013 14:35:05 GMT) Full text and rfc822 format available.Anders Lindgren <andlind <at> gmail.com>
:bug-gnu-emacs <at> gnu.org
.
(Fri, 13 Dec 2013 14:35:07 GMT) Full text and rfc822 format available.Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):
From: Anders Lindgren <andlind <at> gmail.com> To: bug-gnu-emacs <at> gnu.org Subject: 24.3.50; Emacs slow with follow-mode when buffer ends before last window Date: Fri, 13 Dec 2013 15:34:07 +0100
[Message part 1 (text/plain, inline)]
When follow-mode is enabled and the displayed buffer ends before the last window, Emacs becomes extremely slow. This broke on revision 115272 (see log below). Steps to repeat the problem: emacs -Q C-u 10 RET C-x 3 M-x follow-mode RET Here, moving the cursor up or down one line takes about one second. Holding and the arrow keys cause the cursor to disappear until the key is released or the edge of the buffer has been reached. The problem disappears as soon as some parts of the buffer is shown in the rightmost window. I am the original author of follow-mode, so I can share one interesting implementation detail. When the viewed buffer ends before the last window, follow-mode tries to display this window without any content (by setting the window start to point-max). Unfortunately, the Emacs display engine always tries ensure that windows are not empty so it repositions it... So, follow-mode hammers in its view of the world every chance it gets, currrently in post-command hook and window-scroll-functions. Sincerely, Anders Lindgren Ps. Log for revision 115272: revno: 115272 committer: Stefan Monnier <monnier <at> iro.umontreal.ca> branch nick: trunk timestamp: Thu 2013-11-28 17:43:09 -0500 message: Refine redisplay optimizations to only redisplay *some* frames/windows rather than all of them. * src/xdisp.c (REDISPLAY_SOME): New constant. (redisplay_other_windows, wset_redisplay, fset_redisplay) (bset_redisplay, bset_update_mode_line): New functions. (message_dolog): Use bset_redisplay. (clear_garbaged_frames): Use fset_redisplay. (echo_area_display): Use wset_redisplay. (buffer_shared_and_changed): Remove. (prepare_menu_bars): Call Vpre_redisplay_function before updating frame titles. Compute the actual set of windows redisplayed. Don't update frame titles and menu bars for frames that don't need to be redisplayed. (propagate_buffer_redisplay): New function. (AINC): New macro. (redisplay_internal): Use it. Be more selective in the set of windows we redisplay. Propagate windows_or_buffers_changed to update_mode_lines a bit later to simplify the code. (mark_window_display_accurate_1): Reset window and buffer's `redisplay' flag. (redisplay_window): Do nothing if neither the window nor the buffer nor the frame needs redisplay. * src/window.h (struct window): Add `redisplay' field. (wset_redisplay, fset_redisplay, bset_redisplay, bset_update_mode_line) (redisplay_other_windows, window_list): New declarations. * src/window.c (select_window, Fset_window_start): Use wset_redisplay. (window_list): Not static any more. (grow_mini_window, shrink_mini_window): Use fset_redisplay. * src/minibuf.c (read_minibuf_unwind): Don't redisplay everything. * src/insdel.c (prepare_to_modify_buffer_1): Use bset_redisplay. * src/frame.c (Fmake_frame_visible): Don't redisplay everything. * src/frame.h (struct frame): Add `redisplay' field. Move `external_menu_bar' bitfield next to other bit-fields. (SET_FRAME_GARBAGED): Use fset_redisplay. (SET_FRAME_VISIBLE): Don't garbage the frame; Use redisplay_other_windows. * src/buffer.h (struct buffer): Add `redisplay' field. * src/buffer.c (Fforce_mode_line_update): Pay attention to the `all' flag. (modify_overlay): Use bset_redisplay. * src/alloc.c (gc_sweep): Don't unmark strings while sweeping symbols. * lisp/doc-view.el (doc-view-goto-page): Update mode-line. In GNU Emacs 24.3.50.1 (x86_64-apple-darwin13.0.0, NS apple-appkit-1265.00) of 2013-12-13 on macpro.lan Bzr revision: 115272 monnier <at> iro.umontreal.ca-20131128224309-jg2ar5frhpri4yow Windowing system distributor `Apple', version 10.3.1265 Configured using: `configure --with-ns' Important settings: value of $LC_CTYPE: UTF-8 locale-coding-system: utf-8-unix default enable-multibyte-characters: t Major mode: Lisp Interaction Minor modes in effect: follow-mode: t tooltip-mode: t mouse-wheel-mode: t tool-bar-mode: t menu-bar-mode: t file-name-shadow-mode: t global-font-lock-mode: t font-lock-mode: t blink-cursor-mode: t auto-composition-mode: t auto-encryption-mode: t auto-compression-mode: t line-number-mode: t transient-mark-mode: t Recent input: <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> C-x 3 <up> <up> <up> <up> <up> <up> <up> <up> <escape> x f o l l o w - d e <backspace> <backspace> m o d e <return> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> C-h v e m a c s - b z <tab> <return> <up> <up> <up> <up> <up> <up> <up> <up> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <down> <up> <up> <up> <up> <up> <up> C-x o C-x b * s c <tab> <return> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <up> <down> <down> C-x 1 <down> <down> <down> <down> <down> <down> <down> <down> <down> <menu-bar> <help-menu> <send-emacs-bug-report> F o l l o w - m o d e SPC s <backspace> i s SPC <backspace> <backspace> <backspace> <backspace> <backspace> <backspace> <backspace> <backspace> <backspace> <backspace> <backspace> <backspace> <backspace> <backspace> <backspace> R e d i d <backspace> <backspace> <backspace> <backspace> <backspace> E m a c s SPC i s SPC s l o w SPC w h e n SPC f o l l o w - m o d e SPC i s SPC a <backspace> e n a b l e d SPC a n d SPC b u f f e r SPC t a i l C-a <right> <right> <right> <right> <right> <right> <right> <right> <right> <s-backspace> <menu-bar> <help-menu> <send-emacs-bug-report> Recent messages: Beginning of buffer End of buffer Follow mode enabled Beginning of buffer [4 times] End of buffer [13 times] Type "q" in help window to restore its previous buffer. Beginning of buffer [4 times] End of buffer [4 times] Beginning of buffer [6 times] <s-backspace> is undefined Quit Load-path shadows: None found. Features: (shadow sort gnus-util mail-extr emacsbug message format-spec rfc822 mml mml-sec mm-decode mm-bodies mm-encode mail-parse rfc2231 mailabbrev gmm-utils mailheader sendmail rfc2047 rfc2045 ietf-drums mm-util mail-prsvr mail-utils pp help-mode help-fns follow easymenu time-date tooltip ediff-hook vc-hooks lisp-float-type mwheel ns-win tool-bar dnd fontset image regexp-opt fringe tabulated-list newcomment lisp-mode prog-mode register page menu-bar rfn-eshadow timer select scroll-bar mouse jit-lock font-lock syntax facemenu font-core frame cham georgian utf-8-lang misc-lang vietnamese tibetan thai tai-viet lao korean japanese hebrew greek romanian slovak czech european ethiopic indian cyrillic chinese case-table epa-hook jka-cmpr-hook help simple abbrev minibuffer nadvice loaddefs button faces cus-face macroexp files text-properties overlay sha1 md5 base64 format env code-pages mule custom widget hashtable-print-readable backquote make-network-process cocoa ns multi-tty emacs)
[Message part 2 (text/html, inline)]
bug-gnu-emacs <at> gnu.org
:bug#16129
; Package emacs
.
(Fri, 13 Dec 2013 15:33:01 GMT) Full text and rfc822 format available.Message #8 received at 16129 <at> debbugs.gnu.org (full text, mbox):
From: Eli Zaretskii <eliz <at> gnu.org> To: Anders Lindgren <andlind <at> gmail.com> Cc: 16129 <at> debbugs.gnu.org Subject: Re: bug#16129: 24.3.50; Emacs slow with follow-mode when buffer ends before last window Date: Fri, 13 Dec 2013 17:32:22 +0200
> Date: Fri, 13 Dec 2013 15:34:07 +0100 > From: Anders Lindgren <andlind <at> gmail.com> > > I am the original author of follow-mode, so I can share one interesting > implementation detail. When the viewed buffer ends before the last window, > follow-mode tries to display this window without any content (by setting > the window start to point-max). Unfortunately, the Emacs display engine > always tries ensure that windows are not empty so it repositions it... You cannot have window-start and point-max, sorry. Remember: point-max is a buffer position that doesn't really exist, it's beyond the end of buffer text. So it cannot be treated as any other buffer position.
bug-gnu-emacs <at> gnu.org
:bug#16129
; Package emacs
.
(Fri, 13 Dec 2013 15:46:02 GMT) Full text and rfc822 format available.Message #11 received at 16129 <at> debbugs.gnu.org (full text, mbox):
From: Eli Zaretskii <eliz <at> gnu.org> To: andlind <at> gmail.com Cc: 16129 <at> debbugs.gnu.org Subject: Re: bug#16129: 24.3.50; Emacs slow with follow-mode when buffer ends before last window Date: Fri, 13 Dec 2013 17:36:31 +0200
> Date: Fri, 13 Dec 2013 17:32:22 +0200 > From: Eli Zaretskii <eliz <at> gnu.org> > Cc: 16129 <at> debbugs.gnu.org > > You cannot have window-start and point-max, sorry. ^^^ Should be "at", not "and". Btw, why this restriction requires follow-mode to hook all over the place, is not entirely clear to me. Perhaps if you tell the reason(s), a better solution could be found.
bug-gnu-emacs <at> gnu.org
:bug#16129
; Package emacs
.
(Fri, 13 Dec 2013 16:39:01 GMT) Full text and rfc822 format available.Message #14 received at 16129 <at> debbugs.gnu.org (full text, mbox):
From: Stefan Monnier <monnier <at> IRO.UMontreal.CA> To: Anders Lindgren <andlind <at> gmail.com> Cc: 16129 <at> debbugs.gnu.org Subject: Re: bug#16129: 24.3.50; Emacs slow with follow-mode when buffer ends before last window Date: Fri, 13 Dec 2013 11:38:24 -0500
> I am the original author of follow-mode, so I can share one interesting > implementation detail. When the viewed buffer ends before the last window, > follow-mode tries to display this window without any content (by setting > the window start to point-max). Unfortunately, the Emacs display engine > always tries ensure that windows are not empty so it repositions it... So, > follow-mode hammers in its view of the world every chance it gets, > currrently in post-command hook and window-scroll-functions. Hmm.. so we have 2 things to do: 1- figure out why my patch slowed things down so much. 2- change follow-mode to use a different approach. Maybe a good way is to do the following: put window-point at point-max, and add an overlay on window-start...point-max that makes the text invisible (with a `window' property, so it's only invisible in that window). Of course, maybe that won't work either. But hooking everywhere doesn't sound like a good idea. -- Stefab
bug-gnu-emacs <at> gnu.org
:bug#16129
; Package emacs
.
(Fri, 13 Dec 2013 17:56:02 GMT) Full text and rfc822 format available.Message #17 received at 16129 <at> debbugs.gnu.org (full text, mbox):
From: Anders Lindgren <andlind <at> gmail.com> To: Stefan Monnier <monnier <at> iro.umontreal.ca>, Eli Zaretskii <eliz <at> gnu.org> Cc: 16129 <at> debbugs.gnu.org Subject: Re: bug#16129: 24.3.50; Emacs slow with follow-mode when buffer ends before last window Date: Fri, 13 Dec 2013 18:55:11 +0100
[Message part 1 (text/plain, inline)]
Hi! I agree that we would need to find out why the patch makes Emacs slow. (In fact, I only supplied the information about the internals of follow-mode to help you track down the problems with the slowdown.) However, I don't agree with Eli -- it is possible to place window-start at point-max! However, there is code in the display engine that explicitly recenters such windows, after a while, or when something happens. For example: emacs -Q C-x 3 C-x o M-: (set-window-start (selected-window) (point-max)) RET C-x o M-< blablabla (type some text) As you type text in the left window at the beginning of the scratch buffer, the right window is recentered. Follow-mode needs its windows to stay put (even the empty ones), as this is essential in creating the illusion that a number of windows make up a very tall virtual window. When I originally wrote follow-mode (some 18 years ago), I suggested to the Emacs maintainers to add a feature to make the recentering of empty windows conditional, so that follow-mode could control this. However, at the time they were not interested so I continued with the current system, which has worked flawlessly since then. If you are interested in making the change in the display engine, follow-mode should of course be rewritten to use it. Otherwise, I suggest that we keep it as it is today -- solutions using overlays etc. don't appeal to me at all. -- Anders On Fri, Dec 13, 2013 at 5:38 PM, Stefan Monnier <monnier <at> iro.umontreal.ca>wrote: > > I am the original author of follow-mode, so I can share one interesting > > implementation detail. When the viewed buffer ends before the last > window, > > follow-mode tries to display this window without any content (by setting > > the window start to point-max). Unfortunately, the Emacs display engine > > always tries ensure that windows are not empty so it repositions it... > So, > > follow-mode hammers in its view of the world every chance it gets, > > currrently in post-command hook and window-scroll-functions. > > Hmm.. so we have 2 things to do: > 1- figure out why my patch slowed things down so much. > 2- change follow-mode to use a different approach. Maybe a good way is > to do the following: put window-point at point-max, and add an overlay > on window-start...point-max that makes the text invisible (with > a `window' property, so it's only invisible in that window). > Of course, maybe that won't work either. But hooking everywhere > doesn't sound like a good idea. > > > -- Stefab >
[Message part 2 (text/html, inline)]
bug-gnu-emacs <at> gnu.org
:bug#16129
; Package emacs
.
(Thu, 02 Jan 2014 13:57:03 GMT) Full text and rfc822 format available.Message #20 received at 16129 <at> debbugs.gnu.org (full text, mbox):
From: Anders Lindgren <andlind <at> gmail.com> To: Stefan Monnier <monnier <at> iro.umontreal.ca>, Eli Zaretskii <eliz <at> gnu.org> Cc: 16129 <at> debbugs.gnu.org Subject: Re: bug#16129: 24.3.50; Emacs slow with follow-mode when buffer ends before last window Date: Thu, 2 Jan 2014 14:55:59 +0100
[Message part 1 (text/plain, inline)]
Hi again! In addition to the problems I originally reported, I realized today that the modification also made follow-mode place windows incorrectly, which indicates that some primitive display-related function returns incorrect values. Do you want me to report a new bug, or should we see this as a second symptom? You can verify this by doing the following steps: emacs -Q C-h t M-> M-x follow-delete-other-windows-and-split RET C-p C-p After the second C-p, the left window is recentered, which is shouldn't. This typically occurs when follow-mode thinks the point is not visible in any window, which probably is due to incorrect values being reported from primitive functions. (For example, in bug #15957 `window-end' didn't honour it's FORCE argument, since some display functions didn't mark the end value as being dirty.) I will try to track this down in more detail. However, I wanted to give you a heads up since it's appears as though you are close to a release -- it might take me a couple of days to find the problem, as I have very limited time to spend on Emacs-related things. Sincerely, Anders Lindgren On Fri, Dec 13, 2013 at 6:55 PM, Anders Lindgren <andlind <at> gmail.com> wrote: > Hi! > > I agree that we would need to find out why the patch makes Emacs slow. (In > fact, I only supplied the information about the internals of follow-mode to > help you track down the problems with the slowdown.) > > However, I don't agree with Eli -- it is possible to place window-start at > point-max! However, there is code in the display engine that explicitly > recenters such windows, after a while, or when something happens. For > example: > > emacs -Q > C-x 3 > C-x o > M-: (set-window-start (selected-window) (point-max)) RET > C-x o > M-< > blablabla (type some text) > > As you type text in the left window at the beginning of the scratch > buffer, the right window is recentered. Follow-mode needs its windows to > stay put (even the empty ones), as this is essential in creating the > illusion that a number of windows make up a very tall virtual window. > > When I originally wrote follow-mode (some 18 years ago), I suggested to > the Emacs maintainers to add a feature to make the recentering of empty > windows conditional, so that follow-mode could control this. However, at > the time they were not interested so I continued with the current system, > which has worked flawlessly since then. > > If you are interested in making the change in the display engine, > follow-mode should of course be rewritten to use it. Otherwise, I suggest > that we keep it as it is today -- solutions using overlays etc. don't > appeal to me at all. > > -- Anders > > > > On Fri, Dec 13, 2013 at 5:38 PM, Stefan Monnier <monnier <at> iro.umontreal.ca>wrote: > >> > I am the original author of follow-mode, so I can share one interesting >> > implementation detail. When the viewed buffer ends before the last >> window, >> > follow-mode tries to display this window without any content (by setting >> > the window start to point-max). Unfortunately, the Emacs display engine >> > always tries ensure that windows are not empty so it repositions it... >> So, >> > follow-mode hammers in its view of the world every chance it gets, >> > currrently in post-command hook and window-scroll-functions. >> >> Hmm.. so we have 2 things to do: >> 1- figure out why my patch slowed things down so much. >> 2- change follow-mode to use a different approach. Maybe a good way is >> to do the following: put window-point at point-max, and add an overlay >> on window-start...point-max that makes the text invisible (with >> a `window' property, so it's only invisible in that window). >> Of course, maybe that won't work either. But hooking everywhere >> doesn't sound like a good idea. >> >> >> -- Stefab >> > >
[Message part 2 (text/html, inline)]
bug-gnu-emacs <at> gnu.org
:bug#16129
; Package emacs
.
(Thu, 02 Jan 2014 18:40:01 GMT) Full text and rfc822 format available.Message #23 received at 16129 <at> debbugs.gnu.org (full text, mbox):
From: Anders Lindgren <andlind <at> gmail.com> To: Stefan Monnier <monnier <at> iro.umontreal.ca>, Eli Zaretskii <eliz <at> gnu.org> Cc: 16129 <at> debbugs.gnu.org Subject: Re: bug#16129: 24.3.50; Emacs slow with follow-mode when buffer ends before last window Date: Thu, 2 Jan 2014 19:39:21 +0100
[Message part 1 (text/plain, inline)]
Hi again! I've dug a bit more into this. It looks like it's not follow-mode that repositions the window, instead I guess it's some kind of recentering code in the display engine that have gone "crazy". I've managed to reproduce the problem with an extremely cut-down version of the code, which simply reads and restores window-start of windows when windows-start is point-max. To reproduce, do the following: emacs -Q Enter and evaluate the following: (defun my-avoid-tail-recenter (&rest _rest) (let* ((orig-buffer (current-buffer)) (top (frame-first-window)) (win top)) ;; If the only window in the frame is a minibuffer ;; window, `next-window' will never find it again... (unless (window-minibuffer-p top) (while (let ((start (window-start win))) (set-buffer (window-buffer win)) (if (eq (point-max) start) ;; Write the same window start back, but don't ;; set the NOFORCE flag. (set-window-start win start)) (setq win (next-window win 'not t)) (not (eq win top)))) ;; Loop while this is true. (set-buffer orig-buffer)))) (add-hook 'post-command-hook 'my-avoid-tail-recenter) C-x 3 M-: (set-window-start (selected-window) (point-max)) RET C-x o C-p Here, the window will be recentered without there being any reason for it. Note that this will apply to any window in any frame, as long as there is a window where window-start == point-max, even if the window displays a different buffer. As this now falls outside of follow-mode, I think that I have reached the end of what I can contribute... Sincerely, Anders Lindgren On Thu, Jan 2, 2014 at 2:55 PM, Anders Lindgren <andlind <at> gmail.com> wrote: > Hi again! > > In addition to the problems I originally reported, I realized today that > the modification also made follow-mode place windows incorrectly, which > indicates that some primitive display-related function returns incorrect > values. > > Do you want me to report a new bug, or should we see this as a second > symptom? > > You can verify this by doing the following steps: > > emacs -Q > C-h t > M-> > M-x follow-delete-other-windows-and-split RET > C-p > C-p > > After the second C-p, the left window is recentered, which is shouldn't. > This typically occurs when follow-mode thinks the point is not visible in > any window, which probably is due to incorrect values being reported from > primitive functions. (For example, in bug #15957 `window-end' didn't honour > it's FORCE argument, since some display functions didn't mark the end value > as being dirty.) > > I will try to track this down in more detail. However, I wanted to give > you a heads up since it's appears as though you are close to a release -- > it might take me a couple of days to find the problem, as I have very > limited time to spend on Emacs-related things. > > Sincerely, > Anders Lindgren > > > > On Fri, Dec 13, 2013 at 6:55 PM, Anders Lindgren <andlind <at> gmail.com>wrote: > >> Hi! >> >> I agree that we would need to find out why the patch makes Emacs slow. >> (In fact, I only supplied the information about the internals of >> follow-mode to help you track down the problems with the slowdown.) >> >> However, I don't agree with Eli -- it is possible to place window-start >> at point-max! However, there is code in the display engine that explicitly >> recenters such windows, after a while, or when something happens. For >> example: >> >> emacs -Q >> C-x 3 >> C-x o >> M-: (set-window-start (selected-window) (point-max)) RET >> C-x o >> M-< >> blablabla (type some text) >> >> As you type text in the left window at the beginning of the scratch >> buffer, the right window is recentered. Follow-mode needs its windows to >> stay put (even the empty ones), as this is essential in creating the >> illusion that a number of windows make up a very tall virtual window. >> >> When I originally wrote follow-mode (some 18 years ago), I suggested to >> the Emacs maintainers to add a feature to make the recentering of empty >> windows conditional, so that follow-mode could control this. However, at >> the time they were not interested so I continued with the current system, >> which has worked flawlessly since then. >> >> If you are interested in making the change in the display engine, >> follow-mode should of course be rewritten to use it. Otherwise, I suggest >> that we keep it as it is today -- solutions using overlays etc. don't >> appeal to me at all. >> >> -- Anders >> >> >> >> On Fri, Dec 13, 2013 at 5:38 PM, Stefan Monnier <monnier <at> iro.umontreal.ca >> > wrote: >> >>> > I am the original author of follow-mode, so I can share one interesting >>> > implementation detail. When the viewed buffer ends before the last >>> window, >>> > follow-mode tries to display this window without any content (by >>> setting >>> > the window start to point-max). Unfortunately, the Emacs display engine >>> > always tries ensure that windows are not empty so it repositions it... >>> So, >>> > follow-mode hammers in its view of the world every chance it gets, >>> > currrently in post-command hook and window-scroll-functions. >>> >>> Hmm.. so we have 2 things to do: >>> 1- figure out why my patch slowed things down so much. >>> 2- change follow-mode to use a different approach. Maybe a good way is >>> to do the following: put window-point at point-max, and add an overlay >>> on window-start...point-max that makes the text invisible (with >>> a `window' property, so it's only invisible in that window). >>> Of course, maybe that won't work either. But hooking everywhere >>> doesn't sound like a good idea. >>> >>> >>> -- Stefab >>> >> >> >
[Message part 2 (text/html, inline)]
bug-gnu-emacs <at> gnu.org
:bug#16129
; Package emacs
.
(Sun, 05 Jan 2014 23:14:02 GMT) Full text and rfc822 format available.Message #26 received at 16129 <at> debbugs.gnu.org (full text, mbox):
From: Anders Lindgren <andlind <at> gmail.com> To: Stefan Monnier <monnier <at> iro.umontreal.ca>, Eli Zaretskii <eliz <at> gnu.org> Cc: 16129 <at> debbugs.gnu.org Subject: Re: bug#16129: 24.3.50; Emacs slow with follow-mode when buffer ends before last window Date: Mon, 6 Jan 2014 00:13:38 +0100
[Message part 1 (text/plain, inline)]
Hi again! As I haven't heard anything on this bug for a while, I tried to track down the problem myself. I have found something that looks like the cause of the problem, however, I haven't looked into a way to solve it. When "redisplay_window" is called, it goes into the case where "try_cursor_movement" is called. Inside this routine, the row is picked up. The row (when using the TUTORIAL example) has start and end at 46229. The point and last_point, however, are 46228, so it assumes that the point haven't moved since the last redisplay. Clearly, "last_point" and "row" are not consistent with each other, which is assumed by try_cursor_movement (if I read it correctly). The routine first declare this to be a "success" (in the neither forward nor backward case). Later in the function it comes to the following statement: if (PT < MATRIX_ROW_START_CHARPOS (row) || PT > MATRIX_ROW_END_CHARPOS (row)) This fails, making the function return " CURSOR_MOVEMENT_MUST_SCROLL", which is turn cause "redisplay_window" to recenter the window. Please respond if this is enough information for you to track down the problem. Sincerely, Anders Lindgren On Thu, Jan 2, 2014 at 7:39 PM, Anders Lindgren <andlind <at> gmail.com> wrote: > Hi again! > > I've dug a bit more into this. It looks like it's not follow-mode that > repositions the window, instead I guess it's some kind of recentering code > in the display engine that have gone "crazy". > > I've managed to reproduce the problem with an extremely cut-down version > of the code, which simply reads and restores window-start of windows when > windows-start is point-max. > > To reproduce, do the following: > > emacs -Q > Enter and evaluate the following: > > (defun my-avoid-tail-recenter (&rest _rest) > (let* ((orig-buffer (current-buffer)) > (top (frame-first-window)) > (win top)) > ;; If the only window in the frame is a minibuffer > ;; window, `next-window' will never find it again... > (unless (window-minibuffer-p top) > (while > (let ((start (window-start win))) > (set-buffer (window-buffer win)) > (if (eq (point-max) start) > ;; Write the same window start back, but don't > ;; set the NOFORCE flag. > (set-window-start win start)) > (setq win (next-window win 'not t)) > (not (eq win top)))) ;; Loop while this is true. > (set-buffer orig-buffer)))) > > (add-hook 'post-command-hook 'my-avoid-tail-recenter) > > C-x 3 > M-: (set-window-start (selected-window) (point-max)) RET > C-x o > C-p > > Here, the window will be recentered without there being any reason for it. > > Note that this will apply to any window in any frame, as long as there is > a window where window-start == point-max, even if the window displays a > different buffer. > > As this now falls outside of follow-mode, I think that I have reached the > end of what I can contribute... > > Sincerely, > Anders Lindgren > > > > On Thu, Jan 2, 2014 at 2:55 PM, Anders Lindgren <andlind <at> gmail.com> wrote: > >> Hi again! >> >> In addition to the problems I originally reported, I realized today that >> the modification also made follow-mode place windows incorrectly, which >> indicates that some primitive display-related function returns incorrect >> values. >> >> Do you want me to report a new bug, or should we see this as a second >> symptom? >> >> You can verify this by doing the following steps: >> >> emacs -Q >> C-h t >> M-> >> M-x follow-delete-other-windows-and-split RET >> C-p >> C-p >> >> After the second C-p, the left window is recentered, which is shouldn't. >> This typically occurs when follow-mode thinks the point is not visible in >> any window, which probably is due to incorrect values being reported from >> primitive functions. (For example, in bug #15957 `window-end' didn't honour >> it's FORCE argument, since some display functions didn't mark the end value >> as being dirty.) >> >> I will try to track this down in more detail. However, I wanted to give >> you a heads up since it's appears as though you are close to a release -- >> it might take me a couple of days to find the problem, as I have very >> limited time to spend on Emacs-related things. >> >> Sincerely, >> Anders Lindgren >> >> >> >> On Fri, Dec 13, 2013 at 6:55 PM, Anders Lindgren <andlind <at> gmail.com>wrote: >> >>> Hi! >>> >>> I agree that we would need to find out why the patch makes Emacs slow. >>> (In fact, I only supplied the information about the internals of >>> follow-mode to help you track down the problems with the slowdown.) >>> >>> However, I don't agree with Eli -- it is possible to place window-start >>> at point-max! However, there is code in the display engine that explicitly >>> recenters such windows, after a while, or when something happens. For >>> example: >>> >>> emacs -Q >>> C-x 3 >>> C-x o >>> M-: (set-window-start (selected-window) (point-max)) RET >>> C-x o >>> M-< >>> blablabla (type some text) >>> >>> As you type text in the left window at the beginning of the scratch >>> buffer, the right window is recentered. Follow-mode needs its windows to >>> stay put (even the empty ones), as this is essential in creating the >>> illusion that a number of windows make up a very tall virtual window. >>> >>> When I originally wrote follow-mode (some 18 years ago), I suggested to >>> the Emacs maintainers to add a feature to make the recentering of empty >>> windows conditional, so that follow-mode could control this. However, at >>> the time they were not interested so I continued with the current system, >>> which has worked flawlessly since then. >>> >>> If you are interested in making the change in the display engine, >>> follow-mode should of course be rewritten to use it. Otherwise, I suggest >>> that we keep it as it is today -- solutions using overlays etc. don't >>> appeal to me at all. >>> >>> -- Anders >>> >>> >>> >>> On Fri, Dec 13, 2013 at 5:38 PM, Stefan Monnier < >>> monnier <at> iro.umontreal.ca> wrote: >>> >>>> > I am the original author of follow-mode, so I can share one >>>> interesting >>>> > implementation detail. When the viewed buffer ends before the last >>>> window, >>>> > follow-mode tries to display this window without any content (by >>>> setting >>>> > the window start to point-max). Unfortunately, the Emacs display >>>> engine >>>> > always tries ensure that windows are not empty so it repositions >>>> it... So, >>>> > follow-mode hammers in its view of the world every chance it gets, >>>> > currrently in post-command hook and window-scroll-functions. >>>> >>>> Hmm.. so we have 2 things to do: >>>> 1- figure out why my patch slowed things down so much. >>>> 2- change follow-mode to use a different approach. Maybe a good way is >>>> to do the following: put window-point at point-max, and add an >>>> overlay >>>> on window-start...point-max that makes the text invisible (with >>>> a `window' property, so it's only invisible in that window). >>>> Of course, maybe that won't work either. But hooking everywhere >>>> doesn't sound like a good idea. >>>> >>>> >>>> -- Stefab >>>> >>> >>> >> >
[Message part 2 (text/html, inline)]
bug-gnu-emacs <at> gnu.org
:bug#16129
; Package emacs
.
(Mon, 06 Jan 2014 03:46:02 GMT) Full text and rfc822 format available.Message #29 received at 16129 <at> debbugs.gnu.org (full text, mbox):
From: Eli Zaretskii <eliz <at> gnu.org> To: Anders Lindgren <andlind <at> gmail.com> Cc: monnier <at> iro.umontreal.ca, 16129 <at> debbugs.gnu.org Subject: Re: bug#16129: 24.3.50; Emacs slow with follow-mode when buffer ends before last window Date: Mon, 06 Jan 2014 05:45:25 +0200
> Date: Mon, 6 Jan 2014 00:13:38 +0100 > From: Anders Lindgren <andlind <at> gmail.com> > Cc: 16129 <at> debbugs.gnu.org > > When "redisplay_window" is called, it goes into the case where > "try_cursor_movement" is called. > > Inside this routine, the row is picked up. The row (when using the TUTORIAL > example) has start and end at 46229. The point and last_point, however, are > 46228, so it assumes that the point haven't moved since the last redisplay. > > Clearly, "last_point" and "row" are not consistent with each other, which > is assumed by try_cursor_movement (if I read it correctly). > > The routine first declare this to be a "success" (in the neither forward > nor backward case). Later in the function it comes to the following > statement: > > if (PT < MATRIX_ROW_START_CHARPOS (row) > || PT > MATRIX_ROW_END_CHARPOS (row)) > > This fails, making the function return " CURSOR_MOVEMENT_MUST_SCROLL", > which is turn cause "redisplay_window" to recenter the window. Thanks. Your description is correct, and I already found that this is what happens. (The silence doesn't necessarily mean no one is doing anything about the bug report ;-) I didn't yet have the time to figure out why the last_point field of the window is equal to point, while last_cursor_vpos points to the screen line that does not contain point; my current suspicion is that the post-command-hook somehow causes that. But given that this is what happens, you will always see a recenter, because it means Emacs lost track of where point is in the window. When Emacs is confused about this, it always recenters as the last resort. This still doesn't say why redisplay is so slow in this case, which was the initial bug reported here. Stay tuned.
bug-gnu-emacs <at> gnu.org
:bug#16129
; Package emacs
.
(Mon, 06 Jan 2014 08:21:02 GMT) Full text and rfc822 format available.Message #32 received at 16129 <at> debbugs.gnu.org (full text, mbox):
From: Anders Lindgren <andlind <at> gmail.com> To: Eli Zaretskii <eliz <at> gnu.org> Cc: Stefan Monnier <monnier <at> iro.umontreal.ca>, 16129 <at> debbugs.gnu.org Subject: Re: bug#16129: 24.3.50; Emacs slow with follow-mode when buffer ends before last window Date: Mon, 6 Jan 2014 09:20:03 +0100
[Message part 1 (text/plain, inline)]
Hi! I think the incorrect state occurs when the new early exit occurs from redsplay_window. When I added the condition "&& PT == w->last_point", both the recentering problem and speed issues were solved. However, I don't know if this is the correct way to handle this, or if it breaks anything else. -- Anders On Mon, Jan 6, 2014 at 4:45 AM, Eli Zaretskii <eliz <at> gnu.org> wrote: > > Date: Mon, 6 Jan 2014 00:13:38 +0100 > > From: Anders Lindgren <andlind <at> gmail.com> > > Cc: 16129 <at> debbugs.gnu.org > > > > When "redisplay_window" is called, it goes into the case where > > "try_cursor_movement" is called. > > > > Inside this routine, the row is picked up. The row (when using the > TUTORIAL > > example) has start and end at 46229. The point and last_point, however, > are > > 46228, so it assumes that the point haven't moved since the last > redisplay. > > > > Clearly, "last_point" and "row" are not consistent with each other, which > > is assumed by try_cursor_movement (if I read it correctly). > > > > The routine first declare this to be a "success" (in the neither forward > > nor backward case). Later in the function it comes to the following > > statement: > > > > if (PT < MATRIX_ROW_START_CHARPOS (row) > > || PT > MATRIX_ROW_END_CHARPOS (row)) > > > > This fails, making the function return " CURSOR_MOVEMENT_MUST_SCROLL", > > which is turn cause "redisplay_window" to recenter the window. > > Thanks. Your description is correct, and I already found that this is > what happens. (The silence doesn't necessarily mean no one is doing > anything about the bug report ;-) > > I didn't yet have the time to figure out why the last_point field of > the window is equal to point, while last_cursor_vpos points to the > screen line that does not contain point; my current suspicion is that > the post-command-hook somehow causes that. But given that this is > what happens, you will always see a recenter, because it means Emacs > lost track of where point is in the window. When Emacs is confused > about this, it always recenters as the last resort. > > This still doesn't say why redisplay is so slow in this case, which > was the initial bug reported here. Stay tuned. >
[Message part 2 (text/html, inline)]
Eli Zaretskii <eliz <at> gnu.org>
:Anders Lindgren <andlind <at> gmail.com>
:Message #37 received at 16129-done <at> debbugs.gnu.org (full text, mbox):
From: Eli Zaretskii <eliz <at> gnu.org> To: Anders Lindgren <andlind <at> gmail.com> Cc: monnier <at> iro.umontreal.ca, 16129-done <at> debbugs.gnu.org Subject: Re: bug#16129: 24.3.50; Emacs slow with follow-mode when buffer ends before last window Date: Mon, 06 Jan 2014 18:33:02 +0200
> Date: Mon, 6 Jan 2014 09:20:03 +0100 > From: Anders Lindgren <andlind <at> gmail.com> > Cc: Stefan Monnier <monnier <at> iro.umontreal.ca>, 16129 <at> debbugs.gnu.org > > I think the incorrect state occurs when the new early exit occurs from > redsplay_window. When I added the condition "&& PT == w->last_point", both > the recentering problem and speed issues were solved. Indeed, this was my conclusion as well. (Except that PT is not quite right, as the window could be displaying a buffer that is not the current one at that early point in redisplay_window.) What this caused was that the window redisplay was mistakenly skipped, but then we marked that window's display "accurate", which confused the heck out of the display engine. So I installed the patch below to fix this regression, and I'm marking this bug done. Feel free to reopen if there are any leftovers. Btw, I strongly recommend against messing with window-start (or anything else that potentially requires redisplay) in a post-command-hook: doing so disables some important redisplay optimizations, and can easily trigger subtle misfeatures. I suggest to look for a better method to do what follow-mode needs to do, even if that means we'd have to implement a special hook we don't yet have. Thanks. === modified file 'src/xdisp.c' --- src/xdisp.c 2014-01-01 17:44:48 +0000 +++ src/xdisp.c 2014-01-06 16:21:39 +0000 @@ -15621,7 +15621,8 @@ redisplay_window (Lisp_Object window, bo && REDISPLAY_SOME_P () && !w->redisplay && !f->redisplay - && !buffer->text->redisplay) + && !buffer->text->redisplay + && BUF_PT (buffer) == w->last_point) return; /* Make sure that both W's markers are valid. */
bug-gnu-emacs <at> gnu.org
:bug#16129
; Package emacs
.
(Tue, 07 Jan 2014 08:14:01 GMT) Full text and rfc822 format available.Message #40 received at 16129-done <at> debbugs.gnu.org (full text, mbox):
From: Anders Lindgren <andlind <at> gmail.com> To: Eli Zaretskii <eliz <at> gnu.org> Cc: Stefan Monnier <monnier <at> iro.umontreal.ca>, 16129-done <at> debbugs.gnu.org Subject: Re: bug#16129: 24.3.50; Emacs slow with follow-mode when buffer ends before last window Date: Tue, 7 Jan 2014 09:13:19 +0100
[Message part 1 (text/plain, inline)]
Hi! Thanks, I tried it out on the trunk, and it seems to be working correctly! I'm open to reimplementing follow-mode in another way, if you think that it's necessary. However, there are two different uses of set-window-start, and maybe we don't need to change both: * Normally, when the position of the active window change, the start of the other windows are updated. This occurs very infrequent, and it would require a redisplay anyway. * When a window shows the empty tail of a buffer, point-max is "hammered" into window-start to ensure that the display engine doesn't recenter the window. Of the two uses, I only consider the second a problem. However, it would probably be easy to handle if there would be a windows-specific option or call-back that could control if the window should be recentered or not. While I'm at it, I realized today that the responsiveness when using follow-mode was better when running the cursor up and down compared to left and right. When looking into the details I saw that the arrow keys no longer were bound to previous- and next-char, so we need to apply the patch below to follow-mode (I don't have write-access to the archives). Thanks for your help, Anders === modified file 'lisp/follow.el' --- lisp/follow.el 2014-01-01 07:43:34 +0000 +++ lisp/follow.el 2014-01-07 07:48:40 +0000 @@ -311,7 +311,7 @@ (set-default symbol value))) (defvar follow-cache-command-list - '(next-line previous-line forward-char backward-char) + '(next-line previous-line forward-char backward-char right-char left-char) "List of commands that don't require recalculation. In order to be able to use the cache, a command should not change the On Mon, Jan 6, 2014 at 5:33 PM, Eli Zaretskii <eliz <at> gnu.org> wrote: > > Date: Mon, 6 Jan 2014 09:20:03 +0100 > > From: Anders Lindgren <andlind <at> gmail.com> > > Cc: Stefan Monnier <monnier <at> iro.umontreal.ca>, 16129 <at> debbugs.gnu.org > > > > I think the incorrect state occurs when the new early exit occurs from > > redsplay_window. When I added the condition "&& PT == w->last_point", > both > > the recentering problem and speed issues were solved. > > Indeed, this was my conclusion as well. (Except that PT is not quite > right, as the window could be displaying a buffer that is not the > current one at that early point in redisplay_window.) > > What this caused was that the window redisplay was mistakenly skipped, > but then we marked that window's display "accurate", which confused > the heck out of the display engine. > > So I installed the patch below to fix this regression, and I'm marking > this bug done. Feel free to reopen if there are any leftovers. > > Btw, I strongly recommend against messing with window-start (or > anything else that potentially requires redisplay) in a > post-command-hook: doing so disables some important redisplay > optimizations, and can easily trigger subtle misfeatures. I suggest > to look for a better method to do what follow-mode needs to do, even > if that means we'd have to implement a special hook we don't yet have. > > Thanks. > > === modified file 'src/xdisp.c' > --- src/xdisp.c 2014-01-01 17:44:48 +0000 > +++ src/xdisp.c 2014-01-06 16:21:39 +0000 > @@ -15621,7 +15621,8 @@ redisplay_window (Lisp_Object window, bo > && REDISPLAY_SOME_P () > && !w->redisplay > && !f->redisplay > - && !buffer->text->redisplay) > + && !buffer->text->redisplay > + && BUF_PT (buffer) == w->last_point) > return; > > /* Make sure that both W's markers are valid. */ > >
[Message part 2 (text/html, inline)]
bug-gnu-emacs <at> gnu.org
:bug#16129
; Package emacs
.
(Fri, 10 Jan 2014 09:32:01 GMT) Full text and rfc822 format available.Message #43 received at 16129 <at> debbugs.gnu.org (full text, mbox):
From: Eli Zaretskii <eliz <at> gnu.org> To: Anders Lindgren <andlind <at> gmail.com> Cc: monnier <at> iro.umontreal.ca, 16129 <at> debbugs.gnu.org Subject: Re: bug#16129: 24.3.50; Emacs slow with follow-mode when buffer ends before last window Date: Fri, 10 Jan 2014 11:31:49 +0200
> Date: Tue, 7 Jan 2014 09:13:19 +0100 > From: Anders Lindgren <andlind <at> gmail.com> > Cc: Stefan Monnier <monnier <at> iro.umontreal.ca>, 16129-done <at> debbugs.gnu.org > > Thanks, I tried it out on the trunk, and it seems to be working correctly! Thanks for testing. > I'm open to reimplementing follow-mode in another way, if you think that > it's necessary. However, there are two different uses of set-window-start, > and maybe we don't need to change both: > > * Normally, when the position of the active window change, the start of the > other windows are updated. This occurs very infrequent, and it would > require a redisplay anyway. > * When a window shows the empty tail of a buffer, point-max is "hammered" > into window-start to ensure that the display engine doesn't recenter the > window. > > Of the two uses, I only consider the second a problem. I think we should consider both, because they both are detrimental to the efficiency of redisplay. You see, the Emacs redisplay has a very complex problem to solve, because there are a gazillion of ways to change some obscure Lisp data structure that can potentially change what should be on the glass. However, if redisplay needed to examine all those potential changes and decide whether they actually change the displayed portion of the buffer, redisplay would become painfully slow. So we have a lot of optimizations in the display engine, each of which basically says: if none of the following events happened since last redisplay cycle, then this and that potential changes don't need to be considered. Each optimization comes with a list of events that invalidate it. Redisplay basically tries to apply each optimization in sequence, starting from the most aggressive one, until it finds one that can be applied, or falls back to the unoptimized code, which redisplays the entire window. To be able to pull this trick, the display engine maintains a set of flags, each one of which tells whether a particular kind of event happened since last redisplay. These flags are consulted when the display engine must decide which optimization, if any, is applicable. One of these flag variables is the window start point: as long as it stays put, Emacs does not need to bother recomputing it, and does not need to invalidate the information it keeps about where in the buffer text is the window start point, given the current value of point. When a post-command-hook forces a value of window-start, some of these optimizations are inapplicable, so Emacs responsiveness suffers. For example, when follow-mode is on, Emacs frequently needs to redisplay the same window twice in a row, instead of just once. > However, it would probably be easy to handle if there would be a > windows-specific option or call-back that could control if the > window should be recentered or not. That's not what I had in mind. Instead, we could have special code in the display engine that would automatically scroll the other window(s) when follow-mode says they should. IOW, when Emacs redisplays some window because something changed in it, the display engine could decide right there and then that some other windows need to be redisplayed, and moreover, compute their window-start point automatically or by calling some Lisp. After all, the relations that determine the window-start of the windows which participate in follow-mode is quite simple: the next window should begin where the previous one ends. All of this could be done in a single redisplay cycle, thereby avoiding the need for a post-command-hook in the first place. The benefit would be not only a more efficient redisplay, but also faster Emacs, because many commands do not affect any display, and many others do not affect windows that are under follow-mode, so in this case a post-command-hook forces Emacs to perform unnecessary redisplay. > While I'm at it, I realized today that the responsiveness when using > follow-mode was better when running the cursor up and down compared to left > and right. When looking into the details I saw that the arrow keys no > longer were bound to previous- and next-char, so we need to apply the patch > below to follow-mode (I don't have write-access to the archives). I installed this in your name. Thanks.
bug-gnu-emacs <at> gnu.org
:bug#16129
; Package emacs
.
(Fri, 10 Jan 2014 18:53:01 GMT) Full text and rfc822 format available.Message #46 received at 16129 <at> debbugs.gnu.org (full text, mbox):
From: Anders Lindgren <andlind <at> gmail.com> To: Eli Zaretskii <eliz <at> gnu.org> Cc: Stefan Monnier <monnier <at> iro.umontreal.ca>, 16129 <at> debbugs.gnu.org Subject: Re: bug#16129: 24.3.50; Emacs slow with follow-mode when buffer ends before last window Date: Fri, 10 Jan 2014 19:52:18 +0100
[Message part 1 (text/plain, inline)]
Eli, I agree that follow-mode slows down Emacs, even though the effect is more visible now compared to earlier. Up to Emacs 22, it really was fast. With Emacs 23 it feels like there is a definitive slowdown, which is visible e.g. when typing plain text fast and when scrolling window. (In fact, at work where I use Windows, I still use Emacs 22.) Implementing follow-mode in the display engine sounds like a wonderful idea! In fact, when I originally wrote it (back in 1995) I intended it to be a prototype, but I envisioned the real implementation to be done in the display engine. Unfortunately, the people responsible for the display engine at the time didn't like the idea, so I made follow-mode to an all-lisp package. Concretely, how do we proceed from here? I don't have the necessary knowledge of the internals of the display engine and I don't have much time to spend on a major rewrite like this. However, if someone decides to proceed with this, I will try to support them as much that I can. -- Anders On Fri, Jan 10, 2014 at 10:31 AM, Eli Zaretskii <eliz <at> gnu.org> wrote: > > Date: Tue, 7 Jan 2014 09:13:19 +0100 > > From: Anders Lindgren <andlind <at> gmail.com> > > Cc: Stefan Monnier <monnier <at> iro.umontreal.ca>, > 16129-done <at> debbugs.gnu.org > > > > Thanks, I tried it out on the trunk, and it seems to be working > correctly! > > Thanks for testing. > > > I'm open to reimplementing follow-mode in another way, if you think that > > it's necessary. However, there are two different uses of > set-window-start, > > and maybe we don't need to change both: > > > > * Normally, when the position of the active window change, the start of > the > > other windows are updated. This occurs very infrequent, and it would > > require a redisplay anyway. > > * When a window shows the empty tail of a buffer, point-max is "hammered" > > into window-start to ensure that the display engine doesn't recenter the > > window. > > > > Of the two uses, I only consider the second a problem. > > I think we should consider both, because they both are detrimental to > the efficiency of redisplay. > > You see, the Emacs redisplay has a very complex problem to solve, > because there are a gazillion of ways to change some obscure Lisp data > structure that can potentially change what should be on the glass. > However, if redisplay needed to examine all those potential changes > and decide whether they actually change the displayed portion of the > buffer, redisplay would become painfully slow. > > So we have a lot of optimizations in the display engine, each of which > basically says: if none of the following events happened since last > redisplay cycle, then this and that potential changes don't need to be > considered. Each optimization comes with a list of events that > invalidate it. Redisplay basically tries to apply each optimization > in sequence, starting from the most aggressive one, until it finds one > that can be applied, or falls back to the unoptimized code, which > redisplays the entire window. > > To be able to pull this trick, the display engine maintains a set of > flags, each one of which tells whether a particular kind of event > happened since last redisplay. These flags are consulted when the > display engine must decide which optimization, if any, is applicable. > > One of these flag variables is the window start point: as long as it > stays put, Emacs does not need to bother recomputing it, and does not > need to invalidate the information it keeps about where in the buffer > text is the window start point, given the current value of point. > > When a post-command-hook forces a value of window-start, some of these > optimizations are inapplicable, so Emacs responsiveness suffers. For > example, when follow-mode is on, Emacs frequently needs to redisplay > the same window twice in a row, instead of just once. > > > However, it would probably be easy to handle if there would be a > > windows-specific option or call-back that could control if the > > window should be recentered or not. > > That's not what I had in mind. Instead, we could have special code in > the display engine that would automatically scroll the other window(s) > when follow-mode says they should. IOW, when Emacs redisplays some > window because something changed in it, the display engine could > decide right there and then that some other windows need to be > redisplayed, and moreover, compute their window-start point > automatically or by calling some Lisp. After all, the relations that > determine the window-start of the windows which participate in > follow-mode is quite simple: the next window should begin where the > previous one ends. All of this could be done in a single redisplay > cycle, thereby avoiding the need for a post-command-hook in the first > place. The benefit would be not only a more efficient redisplay, but > also faster Emacs, because many commands do not affect any display, > and many others do not affect windows that are under follow-mode, so > in this case a post-command-hook forces Emacs to perform unnecessary > redisplay. > > > While I'm at it, I realized today that the responsiveness when using > > follow-mode was better when running the cursor up and down compared to > left > > and right. When looking into the details I saw that the arrow keys no > > longer were bound to previous- and next-char, so we need to apply the > patch > > below to follow-mode (I don't have write-access to the archives). > > I installed this in your name. Thanks. >
[Message part 2 (text/html, inline)]
bug-gnu-emacs <at> gnu.org
:bug#16129
; Package emacs
.
(Fri, 10 Jan 2014 19:01:01 GMT) Full text and rfc822 format available.Message #49 received at 16129 <at> debbugs.gnu.org (full text, mbox):
From: Eli Zaretskii <eliz <at> gnu.org> To: Anders Lindgren <andlind <at> gmail.com> Cc: monnier <at> iro.umontreal.ca, 16129 <at> debbugs.gnu.org Subject: Re: bug#16129: 24.3.50; Emacs slow with follow-mode when buffer ends before last window Date: Fri, 10 Jan 2014 21:00:17 +0200
> Date: Fri, 10 Jan 2014 19:52:18 +0100 > From: Anders Lindgren <andlind <at> gmail.com> > Cc: Stefan Monnier <monnier <at> iro.umontreal.ca>, 16129 <at> debbugs.gnu.org > > Concretely, how do we proceed from here? I don't have the necessary > knowledge of the internals of the display engine and I don't have much time > to spend on a major rewrite like this. However, if someone decides to > proceed with this, I will try to support them as much that I can. I suggest to file a separate feature request bug report about this, and include in it the requirements for the display engine to support follow-mode. That is, given a set of windows that are "following" each other, what should redisplay do when certain display-related events happen. Then interested volunteers can implement that.
bug-gnu-emacs <at> gnu.org
:bug#16129
; Package emacs
.
(Mon, 13 Jan 2014 11:42:01 GMT) Full text and rfc822 format available.Message #52 received at 16129 <at> debbugs.gnu.org (full text, mbox):
From: Anders Lindgren <andlind <at> gmail.com> To: Eli Zaretskii <eliz <at> gnu.org> Cc: Stefan Monnier <monnier <at> iro.umontreal.ca>, 16129 <at> debbugs.gnu.org Subject: Re: bug#16129: 24.3.50; Emacs slow with follow-mode when buffer ends before last window Date: Mon, 13 Jan 2014 12:41:14 +0100
[Message part 1 (text/plain, inline)]
Sounds like a good idea to post this feature request. However, being a realist, I doubt that this will happen anytime soon. I would suggest that we also post feature requests for things that would help the situation on a shorter time scale. Primarily, I would like to be able, on a window-by-window basis, control whether or not a window should be recentered, when empty. Also, we might look into the speed issues, we might be able to avoid double redraws with little effort, for the common cases. While I'm at it. I updated to the latest trunk today and saw that cursor movements are a lot faster now, including the when the tail is showing. However, I noticed that when the region is active, the region highlight is not updated as fast as it is when follow-mode is off, when running the cursor. -- Anders On Fri, Jan 10, 2014 at 8:00 PM, Eli Zaretskii <eliz <at> gnu.org> wrote: > > Date: Fri, 10 Jan 2014 19:52:18 +0100 > > From: Anders Lindgren <andlind <at> gmail.com> > > Cc: Stefan Monnier <monnier <at> iro.umontreal.ca>, 16129 <at> debbugs.gnu.org > > > > Concretely, how do we proceed from here? I don't have the necessary > > knowledge of the internals of the display engine and I don't have much > time > > to spend on a major rewrite like this. However, if someone decides to > > proceed with this, I will try to support them as much that I can. > > I suggest to file a separate feature request bug report about this, > and include in it the requirements for the display engine to support > follow-mode. That is, given a set of windows that are "following" > each other, what should redisplay do when certain display-related > events happen. Then interested volunteers can implement that. >
[Message part 2 (text/html, inline)]
bug-gnu-emacs <at> gnu.org
:bug#16129
; Package emacs
.
(Mon, 13 Jan 2014 14:48:01 GMT) Full text and rfc822 format available.Message #55 received at 16129 <at> debbugs.gnu.org (full text, mbox):
From: Stefan Monnier <monnier <at> iro.umontreal.ca> To: Anders Lindgren <andlind <at> gmail.com> Cc: Eli Zaretskii <eliz <at> gnu.org>, 16129 <at> debbugs.gnu.org Subject: Re: bug#16129: 24.3.50; Emacs slow with follow-mode when buffer ends before last window Date: Mon, 13 Jan 2014 09:47:50 -0500
> While I'm at it. I updated to the latest trunk today and saw that cursor > movements are a lot faster now, including the when the tail is showing. > However, I noticed that when the region is active, the region highlight is > not updated as fast as it is when follow-mode is off, when running the > cursor. Please make a separate bug-report about this. The region highlighting has been moved to Elisp, and it seems that follow-mode's highlighting code seems to interact poorly with the new behavior. But the good news is that follow-mode could use the new Elisp highlighting to "do it right" (no need to use hacks to try and coerce the redisplay to highlight the region over more than one window). Stefan
bug-gnu-emacs <at> gnu.org
:bug#16129
; Package emacs
.
(Mon, 13 Jan 2014 16:17:02 GMT) Full text and rfc822 format available.Message #58 received at 16129 <at> debbugs.gnu.org (full text, mbox):
From: Eli Zaretskii <eliz <at> gnu.org> To: Anders Lindgren <andlind <at> gmail.com> Cc: monnier <at> iro.umontreal.ca, 16129 <at> debbugs.gnu.org Subject: Re: bug#16129: 24.3.50; Emacs slow with follow-mode when buffer ends before last window Date: Mon, 13 Jan 2014 18:16:00 +0200
> Date: Mon, 13 Jan 2014 12:41:14 +0100 > From: Anders Lindgren <andlind <at> gmail.com> > Cc: Stefan Monnier <monnier <at> iro.umontreal.ca>, 16129 <at> debbugs.gnu.org > > Sounds like a good idea to post this feature request. However, being a > realist, I doubt that this will happen anytime soon. You mean, the list of requirements, or their implementation? I hoped the former should not be too hard to come up with, especially for someone who is familiar with follow-mode. > I would suggest that we also post feature requests for things that would > help the situation on a shorter time scale. Primarily, I would like to be > able, on a window-by-window basis, control whether or not a window should > be recentered, when empty. What should Emacs do instead of recentering a window? > While I'm at it. I updated to the latest trunk today and saw that cursor > movements are a lot faster now, including the when the tail is showing. > However, I noticed that when the region is active, the region highlight is > not updated as fast as it is when follow-mode is off, when running the > cursor. This might be worth a separate bug report (with a recipe, please).
bug-gnu-emacs <at> gnu.org
:bug#16129
; Package emacs
.
(Tue, 14 Jan 2014 12:35:04 GMT) Full text and rfc822 format available.Message #61 received at 16129 <at> debbugs.gnu.org (full text, mbox):
From: Anders Lindgren <andlind <at> gmail.com> To: Eli Zaretskii <eliz <at> gnu.org> Cc: Stefan Monnier <monnier <at> iro.umontreal.ca>, 16129 <at> debbugs.gnu.org Subject: Re: bug#16129: 24.3.50; Emacs slow with follow-mode when buffer ends before last window Date: Tue, 14 Jan 2014 13:34:23 +0100
[Message part 1 (text/plain, inline)]
> > > Sounds like a good idea to post this feature request. However, being a > > realist, I doubt that this will happen anytime soon. > > You mean, the list of requirements, or their implementation? I hoped > the former should not be too hard to come up with, especially for > someone who is familiar with follow-mode. > I mean the implementation -- adding this to the display engine is a major undertaking. If it gets put on hold, or prove more complicated then anticipated, I think that we can improve the current implementation with a relatively small effort. I think that we can come up with a list of requirements relatively easy. Basically, it is supposed to do whatever Follow mode does today, with a few exceptions (well, right now I can only think of one): * It should be applied to all visible windows where Follow mode is active. (Follow mode today only act upon the selected window -- Mainly for efficiency reasons.) > I would suggest that we also post feature requests for things that would > > help the situation on a shorter time scale. Primarily, I would like to be > > able, on a window-by-window basis, control whether or not a window should > > be recentered, when empty. > > What should Emacs do instead of recentering a window? > It should keep the window empty. Follow mode tries to create the illusion of a combining several windows into one very tall window. When the tail of the buffer doesn't reach the last window(s), for example when you have opened a very small file, follow mode wants the remaining window(s) to be empty. Today, Emacs prevents this by recentering them, breaking the illusion. (This, of course, does not apply to the first window in a sequence of windows, because then you still want the normal recentering.) Follow mode, today, sets the window-start to point-max in those windows whenever it has a chance, to prevent the recentering. Stefan wrote: > The region highlighting > has been moved to Elisp, and it seems that follow-mode's highlighting > code seems to interact poorly with the new behavior. > But the good news is that follow-mode could use the new Elisp > highlighting to "do it right" (no need to use hacks to try and coerce > the redisplay to highlight the region over more than one window). I will look into it the first chance I get! Where is the implementation located, and what interface do I have to make it appear in more than one window? The current Follow mode implementation of getting the highlight region into more than one window stopped working years ago (when Emacs decided that it should only show the region in the selected window). -- Anders
[Message part 2 (text/html, inline)]
bug-gnu-emacs <at> gnu.org
:bug#16129
; Package emacs
.
(Tue, 14 Jan 2014 16:26:01 GMT) Full text and rfc822 format available.Message #64 received at 16129 <at> debbugs.gnu.org (full text, mbox):
From: Eli Zaretskii <eliz <at> gnu.org> To: Anders Lindgren <andlind <at> gmail.com> Cc: monnier <at> iro.umontreal.ca, 16129 <at> debbugs.gnu.org Subject: Re: bug#16129: 24.3.50; Emacs slow with follow-mode when buffer ends before last window Date: Tue, 14 Jan 2014 18:25:37 +0200
> Date: Tue, 14 Jan 2014 13:34:23 +0100 > From: Anders Lindgren <andlind <at> gmail.com> > Cc: Stefan Monnier <monnier <at> iro.umontreal.ca>, 16129 <at> debbugs.gnu.org > > I mean the implementation -- adding this to the display engine is a major > undertaking. Depending on the requirements, it might not be that major. > Basically, it is supposed to do whatever Follow mode does today That is not specific enough, especially if you take into consideration that I have only a vague idea about what Follow mode does. Moreover, I'm not sure we should ask the display engine do everything it does. For example, selecting the next/previous window when point moves off the limits of the current window seems to be something that is easy to do in Lisp. So please do try to come up with a list of requirements that should be moved to the display engine. I guess setting the window start point when scrolling would be one; what else? > > I would suggest that we also post feature requests for things that would > > > help the situation on a shorter time scale. Primarily, I would like to be > > > able, on a window-by-window basis, control whether or not a window should > > > be recentered, when empty. > > > > What should Emacs do instead of recentering a window? > > > > It should keep the window empty. Shouldn't be hard to implement, given some buffer-local variable.
bug-gnu-emacs <at> gnu.org
:bug#16129
; Package emacs
.
(Thu, 16 Jan 2014 12:25:01 GMT) Full text and rfc822 format available.Message #67 received at 16129 <at> debbugs.gnu.org (full text, mbox):
From: Anders Lindgren <andlind <at> gmail.com> To: Eli Zaretskii <eliz <at> gnu.org> Cc: Stefan Monnier <monnier <at> iro.umontreal.ca>, 16129 <at> debbugs.gnu.org Subject: Re: bug#16129: 24.3.50; Emacs slow with follow-mode when buffer ends before last window Date: Thu, 16 Jan 2014 13:24:16 +0100
[Message part 1 (text/plain, inline)]
> > > Basically, it is supposed to do whatever Follow mode does today > > That is not specific enough, especially if you take into consideration > that I have only a vague idea about what Follow mode does. Moreover, > I'm not sure we should ask the display engine do everything it does. > For example, selecting the next/previous window when point moves off > the limits of the current window seems to be something that is easy to > do in Lisp. > > So please do try to come up with a list of requirements that should be > moved to the display engine. I guess setting the window start point > when scrolling would be one; what else? > You're absolutely correct. Most of Follow mode functions could be kept in elisp. In fact, most of them are trivial, take scrolling for example, it simple moves the current window down a suitable amount, and let the post-command hook take care of the rest. As a starting point, I would say that it's main responsibility is to keep the windows aligned, so that one window start where the previous left of. The second thing it should do is that it should "auto select" other windows when, for example, the cursor moved down below the end of the window. In short, do what the post-command-hook does. I will try to give you a deeper description as soon as I can find some time to do it. > > > I would suggest that we also post feature requests for things that > would > > > > help the situation on a shorter time scale. Primarily, I would like > to be > > > > able, on a window-by-window basis, control whether or not a window > should > > > > be recentered, when empty. > > > > > > What should Emacs do instead of recentering a window? > > > > > > > It should keep the window empty. > > Shouldn't be hard to implement, given some buffer-local variable. > Great. I would suggest that it should be implemented so that the actual test could be written in elisp. In the Follow mode case, the test should be that the buffer is in Follow mode and that it's not the first window. However, I could think of other modes -- one example being Two-column mode, another Scroll all mode -- where this could be useful, but with other criterias. In the simplest form it could be a symbol, nil for "no", t for "yes", and for all other cases call the function it is bound to. Of course, one could make it into a hook, so that more than one mode could have a say, but I think that might be overengineering it a bit... -- Anders
[Message part 2 (text/html, inline)]
bug-gnu-emacs <at> gnu.org
:bug#16129
; Package emacs
.
(Thu, 16 Jan 2014 14:43:02 GMT) Full text and rfc822 format available.Message #70 received at 16129 <at> debbugs.gnu.org (full text, mbox):
From: Stefan Monnier <monnier <at> iro.umontreal.ca> To: Anders Lindgren <andlind <at> gmail.com> Cc: Eli Zaretskii <eliz <at> gnu.org>, 16129 <at> debbugs.gnu.org Subject: Re: bug#16129: 24.3.50; Emacs slow with follow-mode when buffer ends before last window Date: Thu, 16 Jan 2014 09:42:21 -0500
> Great. I would suggest that it should be implemented so that the actual > test could be written in elisp. Yes, clearly. > In the Follow mode case, the test should be that the buffer is in > Follow mode and that it's not the first window. If we can avoid running Elisp code redisplay, it's always better. So since the behavior is not the same for all windows of a buffer, maybe a window-parameter is a better option than a buffer-local value. > In the simplest form it could be a symbol, nil for "no", t for "yes", and > for all other cases call the function it is bound to. Of course, one could > make it into a hook, so that more than one mode could have a say, but I > think that might be overengineering it a bit... A single function is sufficient since you can "share" it with add-function. Stefan
Debbugs Internal Request <help-debbugs <at> gnu.org>
to internal_control <at> debbugs.gnu.org
.
(Fri, 14 Feb 2014 12:24:04 GMT) Full text and rfc822 format available.
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.