* bug#16526: 24.3.50; scroll-conservatively & c-mode regression @ 2014-01-23 8:53 ` martin rudalics 2014-01-24 15:45 ` martin rudalics ` (2 more replies) 0 siblings, 3 replies; 93+ messages in thread From: martin rudalics @ 2014-01-23 8:53 UTC (permalink / raw) To: 16526 With current trunk and emacs -Q evaluating the following form takes more than two minutes here with builds on Windows and GNU/Linux: (progn (setq scroll-conservatively 101) (find-file (concat source-directory "src/xdisp.c")) (end-of-buffer) (sit-for 3) (beginning-of-buffer)) It used to take about 10 seconds before revision 116070. martin ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-01-23 8:53 ` bug#16526: 24.3.50; scroll-conservatively & c-mode regression martin rudalics @ 2014-01-24 15:45 ` martin rudalics 2014-01-24 20:48 ` Alan Mackenzie [not found] ` <lbujij$1scv$1@colin.muc.de> 2 siblings, 0 replies; 93+ messages in thread From: martin rudalics @ 2014-01-24 15:45 UTC (permalink / raw) To: 16526; +Cc: Alan Mackenzie What happens is that apparently back_comment 530 times scans the buffer from the beginning of the buffer to the first comment before the current position where the list of current positions goes like this: (780 14143 15852 18026 20032 20480 21464 21846 22845 23484 25453 26968 ... 942907 943099 944334 948653 948830 948653 948830 948653 948830 948653 948830 780 12) The bug makes working with c-mode virtually impossible here. So until a correct solution to the problem is found I intend to install the patch below in order to get back a working environment. martin === modified file 'src/syntax.c' --- src/syntax.c 2014-01-01 07:43:34 +0000 +++ src/syntax.c 2014-01-24 15:24:00 +0000 @@ -530,7 +530,8 @@ { ptrdiff_t opoint = PT, opoint_byte = PT_BYTE; - if (!open_paren_in_column_0_is_defun_start) + if (!open_paren_in_column_0_is_defun_start + && !open_paren_in_column_0_is_hard_defun_start) { find_start_value = BEGV; find_start_value_byte = BEGV_BYTE; @@ -538,6 +539,7 @@ find_start_modiff = MODIFF; find_start_begv = BEGV; find_start_pos = pos; + return BEGV; } @@ -808,7 +810,8 @@ case Sopen: /* Assume a defun-start point is outside of strings. */ - if (open_paren_in_column_0_is_defun_start + if ((open_paren_in_column_0_is_defun_start + || open_paren_in_column_0_is_hard_defun_start) && (from == stop || (temp_byte = dec_bytepos (from_byte), FETCH_CHAR (temp_byte) == '\n'))) @@ -3608,6 +3611,10 @@ doc: /* Non-nil means an open paren in column 0 denotes the start of a defun. */); open_paren_in_column_0_is_defun_start = 1; + DEFVAR_BOOL ("open-paren-in-column-0-is-hard-defun-start", + open_paren_in_column_0_is_hard_defun_start, + doc: /* Non-nil means an open paren in column 0 does denote the start of a defun. */); + open_paren_in_column_0_is_hard_defun_start = 0; DEFVAR_LISP ("find-word-boundary-function-table", Vfind_word_boundary_function_table, ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-01-23 8:53 ` bug#16526: 24.3.50; scroll-conservatively & c-mode regression martin rudalics 2014-01-24 15:45 ` martin rudalics @ 2014-01-24 20:48 ` Alan Mackenzie [not found] ` <lbujij$1scv$1@colin.muc.de> 2 siblings, 0 replies; 93+ messages in thread From: Alan Mackenzie @ 2014-01-24 20:48 UTC (permalink / raw) To: gnu-emacs-bug Hello, Martin. martin rudalics <rudalics@gmx.at> wrote: > With current trunk and emacs -Q evaluating the following form takes more > than two minutes here with builds on Windows and GNU/Linux: > (progn > (setq scroll-conservatively 101) > (find-file (concat source-directory "src/xdisp.c")) > (end-of-buffer) > (sit-for 3) > (beginning-of-buffer)) > It used to take about 10 seconds before revision 116070. It's taking me about 7 seconds, on an Emacs version whose latest applied revision is 116070. Quick update to current (latest revision 116146), and rebuild ....... It's still taking me about 7 seconds. As far as I can see, you haven't installed your temporary patch to syntax.c. So, I haven't been able to reproduce the problem yet. Is there something more subtle I'm missing? [P.S. isn't it good that we can use revision numbers to identify approximate ages of repository states. ;-] > martin -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 93+ messages in thread
[parent not found: <lbujij$1scv$1@colin.muc.de>]
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression [not found] ` <lbujij$1scv$1@colin.muc.de> @ 2014-01-25 3:50 ` Juanma Barranquero 2014-01-25 9:23 ` martin rudalics [not found] ` <52E38286.1050306@gmx.at> 2 siblings, 0 replies; 93+ messages in thread From: Juanma Barranquero @ 2014-01-25 3:50 UTC (permalink / raw) To: Alan Mackenzie; +Cc: 16526 On Fri, Jan 24, 2014 at 9:48 PM, Alan Mackenzie <acm@muc.de> wrote: > It's still taking me about 7 seconds. As far as I can see, you haven't > installed your temporary patch to syntax.c. So, I haven't been able to > reproduce the problem yet. > > Is there something more subtle I'm missing? On Windows, with current trunk, I see the same slowdown that Martin reports. J ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression [not found] ` <lbujij$1scv$1@colin.muc.de> 2014-01-25 3:50 ` Juanma Barranquero @ 2014-01-25 9:23 ` martin rudalics [not found] ` <52E38286.1050306@gmx.at> 2 siblings, 0 replies; 93+ messages in thread From: martin rudalics @ 2014-01-25 9:23 UTC (permalink / raw) To: 16526; +Cc: Alan Mackenzie >> With current trunk and emacs -Q evaluating the following form takes more >> than two minutes here with builds on Windows and GNU/Linux: > >> (progn >> (setq scroll-conservatively 101) >> (find-file (concat source-directory "src/xdisp.c")) >> (end-of-buffer) >> (sit-for 3) >> (beginning-of-buffer)) > >> It used to take about 10 seconds before revision 116070. > > It's taking me about 7 seconds, on an Emacs version whose latest applied > revision is 116070. > > Quick update to current (latest revision 116146), and rebuild ....... > > It's still taking me about 7 seconds. Updated to revision 116153, bootstrapped (at least one hour on my machine), still taking more than two minutes here. > As far as I can see, you haven't > installed your temporary patch to syntax.c. I'm afraid I have to do that now. > So, I haven't been able to > reproduce the problem yet. > > Is there something more subtle I'm missing? Is there something more subtle I'm missing? > [P.S. isn't it good that we can use revision numbers to identify > approximate ages of repository states. ;-] It didn't help so far in this case ... martin ^ permalink raw reply [flat|nested] 93+ messages in thread
[parent not found: <52E38286.1050306@gmx.at>]
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression [not found] ` <52E38286.1050306@gmx.at> @ 2014-01-25 10:30 ` Eli Zaretskii 2014-01-25 14:58 ` martin rudalics [not found] ` <52E3D131.2090705@gmx.at> 0 siblings, 2 replies; 93+ messages in thread From: Eli Zaretskii @ 2014-01-25 10:30 UTC (permalink / raw) To: martin rudalics; +Cc: acm, 16526 > Date: Sat, 25 Jan 2014 10:23:18 +0100 > From: martin rudalics <rudalics@gmx.at> > Cc: Alan Mackenzie <acm@muc.de> > > >> With current trunk and emacs -Q evaluating the following form takes more > >> than two minutes here with builds on Windows and GNU/Linux: > > > >> (progn > >> (setq scroll-conservatively 101) > >> (find-file (concat source-directory "src/xdisp.c")) > >> (end-of-buffer) > >> (sit-for 3) > >> (beginning-of-buffer)) > > > >> It used to take about 10 seconds before revision 116070. > > > > It's taking me about 7 seconds, on an Emacs version whose latest applied > > revision is 116070. > > > > Quick update to current (latest revision 116146), and rebuild ....... > > > > It's still taking me about 7 seconds. > > Updated to revision 116153, bootstrapped (at least one hour on my > machine), still taking more than two minutes here. I see this too, both on Windows and on GNU/Linux. Here's the profile: - redisplay_internal (C function) 2560 95% - jit-lock-function 2560 95% - jit-lock-fontify-now 2560 95% - funcall 2560 95% - #<compiled 0x4093379> 2560 95% - run-hook-with-args 2560 95% - font-lock-fontify-region 2560 95% - c-font-lock-fontify-region 2560 95% - font-lock-default-fontify-region 2559 95% - font-lock-fontify-keywords-region 2547 94% - c-font-lock-complex-decl-prepare 2543 94% - c-parse-state 2543 94% - c-parse-state-1 2543 94% - c-append-lower-brace-pair-to-state-cache 2542 94% byte-code 2542 94% - c-append-to-state-cache 1 0% byte-code 1 0% + #<compiled 0x407e625> 3 0% + c-font-lock-enum-tail 1 0% + font-lock-fontify-syntactically-region 12 0% + mapc 1 0% + command-execute 116 4% + ... 6 0% This takes about 40 seconds on a fast (Core i7) machine. > > As far as I can see, you haven't > > installed your temporary patch to syntax.c. > > I'm afraid I have to do that now. > > > So, I haven't been able to > > reproduce the problem yet. > > > > Is there something more subtle I'm missing? > > Is there something more subtle I'm missing? Probably. I actually don't understand how come scroll-conservatively affects non-scrolling commands. Can you elaborate on that? You also mentioned back_comment doing something unreasonable. Can you expand on that, too? This part specifically I don't understand: > What happens is that apparently back_comment 530 times scans the buffer > from the beginning of the buffer to the first comment before the current > position where the list of current positions goes like this: Since the problem happens as result of beginning-of-buffer, why would back_comment need to "scan the buffer from the beginning of the buffer to the first comment before the current position"? And what is the current position in this case? Btw, if I disable font-lock ("M-x global-font-lock-mode RET") before repeating the recipe, the move to bob is instantaneous, and turning on font-lock after that doesn't seem to have any adverse effects on responsiveness. ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-01-25 10:30 ` Eli Zaretskii @ 2014-01-25 14:58 ` martin rudalics [not found] ` <52E3D131.2090705@gmx.at> 1 sibling, 0 replies; 93+ messages in thread From: martin rudalics @ 2014-01-25 14:58 UTC (permalink / raw) To: Eli Zaretskii; +Cc: acm, 16526 > Probably. I actually don't understand how come scroll-conservatively > affects non-scrolling commands. Can you elaborate on that? How should I know? I suppose redisplay_window eventually winds up calling the fontification function and sooner or later the c-code calls back_comment. > You also mentioned back_comment doing something unreasonable. Can you > expand on that, too? This part specifically I don't understand: > >> What happens is that apparently back_comment 530 times scans the buffer >> from the beginning of the buffer to the first comment before the current >> position where the list of current positions goes like this: > > Since the problem happens as result of beginning-of-buffer, why would > back_comment need to "scan the buffer from the beginning of the buffer > to the first comment before the current position"? And what is the > current position in this case? I earlier posted the first and last positions here: (780 14143 15852 18026 20032 20480 21464 21846 22845 23484 25453 26968 ... 942907 943099 944334 948653 948830 948653 948830 948653 948830 948653 948830 780 12) You can try by yourself. I gathered the positions in the following excerpt find_defun_start (ptrdiff_t pos, ptrdiff_t pos_byte) { ptrdiff_t opoint = PT, opoint_byte = PT_BYTE; if (!open_paren_in_column_0_is_defun_start) { find_start_value = BEGV; find_start_value_byte = BEGV_BYTE; find_start_buffer = current_buffer; find_start_modiff = MODIFF; find_start_begv = BEGV; find_start_pos = pos; <---------------------------- right here return BEGV; } > Btw, if I disable font-lock ("M-x global-font-lock-mode RET") before > repeating the recipe, the move to bob is instantaneous, and turning on > font-lock after that doesn't seem to have any adverse effects on > responsiveness. Sure. The problem happens obviously via jit-lock. But IMHO disabling `open-paren-in-column-0-is-defun-start' IS asking for trouble as long as back_comment doesn't rely on `syntax-ppss' to find a safe position. martin ^ permalink raw reply [flat|nested] 93+ messages in thread
[parent not found: <52E3D131.2090705@gmx.at>]
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression [not found] ` <52E3D131.2090705@gmx.at> @ 2014-01-25 16:30 ` Eli Zaretskii 2014-01-25 16:48 ` martin rudalics 2014-01-25 20:27 ` bug#16526: 24.3.50; scroll-conservatively & c-mode regression. The purpose of revision 116070 Alan Mackenzie [not found] ` <20140125202721.GA3630@acm.acm> 2 siblings, 1 reply; 93+ messages in thread From: Eli Zaretskii @ 2014-01-25 16:30 UTC (permalink / raw) To: martin rudalics; +Cc: acm, 16526 > Date: Sat, 25 Jan 2014 15:58:57 +0100 > From: martin rudalics <rudalics@gmx.at> > CC: 16526@debbugs.gnu.org, acm@muc.de > > > Probably. I actually don't understand how come scroll-conservatively > > affects non-scrolling commands. Can you elaborate on that? > > How should I know? I suppose redisplay_window eventually winds up > calling the fontification function and sooner or later the c-code calls > back_comment. Yes, that's what happens. And it cannot be avoided, AFAICS, when scroll-conservatively is on. > > You also mentioned back_comment doing something unreasonable. Can you > > expand on that, too? This part specifically I don't understand: > > > >> What happens is that apparently back_comment 530 times scans the buffer > >> from the beginning of the buffer to the first comment before the current > >> position where the list of current positions goes like this: > > > > Since the problem happens as result of beginning-of-buffer, why would > > back_comment need to "scan the buffer from the beginning of the buffer > > to the first comment before the current position"? And what is the > > current position in this case? > > I earlier posted the first and last positions here: > > (780 14143 15852 18026 20032 20480 21464 21846 22845 23484 25453 26968 > ... > 942907 943099 944334 948653 948830 948653 948830 948653 948830 948653 > 948830 780 12) What I see is that find_defun_start is called many times, with its first argument moving from _end_ of the buffer backwards. This happens when Emacs needs to redisplay the last portion of the buffer, immediately after the call to end-of-buffer. Alan, I suspect that you tried to reproduce this without setting scroll-conservatively to a value above 100. Because otherwise this is 100% reproducible. If you still cannot reproduce this, please tell us what information to collect for you. > > Btw, if I disable font-lock ("M-x global-font-lock-mode RET") before > > repeating the recipe, the move to bob is instantaneous, and turning on > > font-lock after that doesn't seem to have any adverse effects on > > responsiveness. > > Sure. The problem happens obviously via jit-lock. JIT Lock is triggered also when font-lock is turned on after the move to end of the buffer. But the difference seems to come from the fact that under scroll-conservatively, we examine the buffer a little bit above/below the window, when we decide where to put window-start. ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-01-25 16:30 ` Eli Zaretskii @ 2014-01-25 16:48 ` martin rudalics 2014-01-25 17:29 ` Eli Zaretskii 0 siblings, 1 reply; 93+ messages in thread From: martin rudalics @ 2014-01-25 16:48 UTC (permalink / raw) To: Eli Zaretskii; +Cc: acm, 16526 >> How should I know? I suppose redisplay_window eventually winds up >> calling the fontification function and sooner or later the c-code calls >> back_comment. > > Yes, that's what happens. And it cannot be avoided, AFAICS, when > scroll-conservatively is on. Well ... so you know why it calls back_comment around the END of the buffer? > What I see is that find_defun_start is called many times, ... 530 times as I mentioned earlier ... > with its > first argument moving from _end_ of the buffer backwards. Not monotonously. Sometimes it's called from the same position (for example 948653 is at least three times on my list) again. > This > happens when Emacs needs to redisplay the last portion of the buffer, > immediately after the call to end-of-buffer. Hmm ... but the problem is when going to BOB. > JIT Lock is triggered also when font-lock is turned on after the move > to end of the buffer. But the difference seems to come from the fact > that under scroll-conservatively, we examine the buffer a little bit > above/below the window, when we decide where to put window-start. And somehow a "current position" is still near the end of the buffer at that time. martin ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-01-25 16:48 ` martin rudalics @ 2014-01-25 17:29 ` Eli Zaretskii 2014-01-25 18:25 ` martin rudalics [not found] ` <52E4019C.5080905@gmx.at> 0 siblings, 2 replies; 93+ messages in thread From: Eli Zaretskii @ 2014-01-25 17:29 UTC (permalink / raw) To: martin rudalics; +Cc: acm, 16526 > Date: Sat, 25 Jan 2014 17:48:02 +0100 > From: martin rudalics <rudalics@gmx.at> > CC: 16526@debbugs.gnu.org, acm@muc.de > > >> How should I know? I suppose redisplay_window eventually winds up > >> calling the fontification function and sooner or later the c-code calls > >> back_comment. > > > > Yes, that's what happens. And it cannot be avoided, AFAICS, when > > scroll-conservatively is on. > > Well ... so you know why it calls back_comment around the END of the > buffer? It starts at the end of the buffer, but then moves all the way back to the beginning. And yes, I know why: it's because scroll-conservatively causes redisplay to examine buffer text around point, when it decides where to place window-start. This is triggered by redisplay after the move to the end of the buffer. > > What I see is that find_defun_start is called many times, > > ... 530 times as I mentioned earlier ... > > > with its > > first argument moving from _end_ of the buffer backwards. > > Not monotonously. Sometimes it's called from the same position (for > example 948653 is at least three times on my list) again. True. But I'm not sure this is relevant to the slow redisplay. > > This > > happens when Emacs needs to redisplay the last portion of the buffer, > > immediately after the call to end-of-buffer. > > Hmm ... but the problem is when going to BOB. No, going to BOB is instantaneous. The problem happens in redisplay after going to EOB. > > JIT Lock is triggered also when font-lock is turned on after the move > > to end of the buffer. But the difference seems to come from the fact > > that under scroll-conservatively, we examine the buffer a little bit > > above/below the window, when we decide where to put window-start. > > And somehow a "current position" is still near the end of the buffer at > that time. Yes, because Emacs is at EOB. ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-01-25 17:29 ` Eli Zaretskii @ 2014-01-25 18:25 ` martin rudalics [not found] ` <52E4019C.5080905@gmx.at> 1 sibling, 0 replies; 93+ messages in thread From: martin rudalics @ 2014-01-25 18:25 UTC (permalink / raw) To: Eli Zaretskii; +Cc: acm, 16526 >> Well ... so you know why it calls back_comment around the END of the >> buffer? > > It starts at the end of the buffer, but then moves all the way back > to the beginning. IIUC `beginning-of-buffer' does set_point_both. Does that move all the way back to the beginning? > And yes, I know why: it's because scroll-conservatively causes > redisplay to examine buffer text around point, Where is `point' at that time? > when it decides where > to place window-start. This is triggered by redisplay after the move > to the end of the buffer. But the `end-of-buffer' call terminates cleanly after a few seconds - that's what the `sit-for' proves in my code. >> > What I see is that find_defun_start is called many times, >> >> ... 530 times as I mentioned earlier ... >> >> > with its >> > first argument moving from _end_ of the buffer backwards. >> >> Not monotonously. Sometimes it's called from the same position (for >> example 948653 is at least three times on my list) again. > > True. But I'm not sure this is relevant to the slow redisplay. It hints at some really bad code embedded in really bad code. >> > This >> > happens when Emacs needs to redisplay the last portion of the buffer, >> > immediately after the call to end-of-buffer. >> >> Hmm ... but the problem is when going to BOB. > > No, going to BOB is instantaneous. The problem happens in redisplay > after going to EOB. EOB happens before my `sit-for'. >> > JIT Lock is triggered also when font-lock is turned on after the move >> > to end of the buffer. But the difference seems to come from the fact >> > that under scroll-conservatively, we examine the buffer a little bit >> > above/below the window, when we decide where to put window-start. >> >> And somehow a "current position" is still near the end of the buffer at >> that time. > > Yes, because Emacs is at EOB. Why? martin ^ permalink raw reply [flat|nested] 93+ messages in thread
[parent not found: <52E4019C.5080905@gmx.at>]
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression [not found] ` <52E4019C.5080905@gmx.at> @ 2014-01-25 18:31 ` Eli Zaretskii 2014-01-25 18:40 ` Eli Zaretskii 2014-01-26 11:19 ` martin rudalics 0 siblings, 2 replies; 93+ messages in thread From: Eli Zaretskii @ 2014-01-25 18:31 UTC (permalink / raw) To: martin rudalics; +Cc: acm, 16526 > Date: Sat, 25 Jan 2014 19:25:32 +0100 > From: martin rudalics <rudalics@gmx.at> > CC: 16526@debbugs.gnu.org, acm@muc.de > > >> Well ... so you know why it calls back_comment around the END of the > >> buffer? > > > > It starts at the end of the buffer, but then moves all the way back > > to the beginning. > > IIUC `beginning-of-buffer' does set_point_both. Does that move all the > way back to the beginning? Of course not, it jumps there in one go. > > And yes, I know why: it's because scroll-conservatively causes > > redisplay to examine buffer text around point, > > Where is `point' at that time? At EOB. > > when it decides where > > to place window-start. This is triggered by redisplay after the move > > to the end of the buffer. > > But the `end-of-buffer' call terminates cleanly after a few seconds - > that's what the `sit-for' proves in my code. Right, and that's when redisplay kicks in, which invokes JIT Lock. > >> Not monotonously. Sometimes it's called from the same position (for > >> example 948653 is at least three times on my list) again. > > > > True. But I'm not sure this is relevant to the slow redisplay. > > It hints at some really bad code embedded in really bad code. Not necessarily. Sometimes, this cannot be avoided. More thorough analysis is needed to determine whether it's really bad code. > >> > This > >> > happens when Emacs needs to redisplay the last portion of the buffer, > >> > immediately after the call to end-of-buffer. > >> > >> Hmm ... but the problem is when going to BOB. > > > > No, going to BOB is instantaneous. The problem happens in redisplay > > after going to EOB. > > EOB happens before my `sit-for'. See above. Redisplay is separate from command execution. So yes, we are already at EOB, and then redisplay happens. > >> > JIT Lock is triggered also when font-lock is turned on after the move > >> > to end of the buffer. But the difference seems to come from the fact > >> > that under scroll-conservatively, we examine the buffer a little bit > >> > above/below the window, when we decide where to put window-start. > >> > >> And somehow a "current position" is still near the end of the buffer at > >> that time. > > > > Yes, because Emacs is at EOB. > > Why? Because we moved there with end-of-buffer. ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-01-25 18:31 ` Eli Zaretskii @ 2014-01-25 18:40 ` Eli Zaretskii 2014-01-26 11:20 ` martin rudalics [not found] ` <52E4EF61.3050404@gmx.at> 2014-01-26 11:19 ` martin rudalics 1 sibling, 2 replies; 93+ messages in thread From: Eli Zaretskii @ 2014-01-25 18:40 UTC (permalink / raw) To: rudalics; +Cc: acm, 16526 > Date: Sat, 25 Jan 2014 20:31:10 +0200 > From: Eli Zaretskii <eliz@gnu.org> > Cc: acm@muc.de, 16526@debbugs.gnu.org > > > > when it decides where > > > to place window-start. This is triggered by redisplay after the move > > > to the end of the buffer. > > > > But the `end-of-buffer' call terminates cleanly after a few seconds - > > that's what the `sit-for' proves in my code. > > Right, and that's when redisplay kicks in, which invokes JIT Lock. More accurately, end-of-buffer calls recenter, which needs to compute where to put window-start, which requires Emacs to examine the text before point. As part of this examination, we invoke functions that simulate display, and those trigger JIT Lock, whose fontification function starts the madness. ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-01-25 18:40 ` Eli Zaretskii @ 2014-01-26 11:20 ` martin rudalics [not found] ` <52E4EF61.3050404@gmx.at> 1 sibling, 0 replies; 93+ messages in thread From: martin rudalics @ 2014-01-26 11:20 UTC (permalink / raw) To: Eli Zaretskii; +Cc: acm, 16526 > More accurately, end-of-buffer calls recenter, which needs to compute > where to put window-start, which requires Emacs to examine the text > before point. As part of this examination, we invoke functions that > simulate display, and those trigger JIT Lock, whose fontification > function starts the madness. This doesn't match my observations. With my shortened scenario (progn (setq scroll-conservatively 101) (find-file (concat source-directory "src/xdisp.c")) (end-of-buffer) (sit-for 3)) there is no such problem. Please enlighten. I must be missing something. martin ^ permalink raw reply [flat|nested] 93+ messages in thread
[parent not found: <52E4EF61.3050404@gmx.at>]
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression [not found] ` <52E4EF61.3050404@gmx.at> @ 2014-01-26 17:20 ` Eli Zaretskii 2014-01-26 20:43 ` Alan Mackenzie 2014-01-27 8:20 ` martin rudalics 0 siblings, 2 replies; 93+ messages in thread From: Eli Zaretskii @ 2014-01-26 17:20 UTC (permalink / raw) To: martin rudalics; +Cc: acm, 16526 > Date: Sun, 26 Jan 2014 12:20:01 +0100 > From: martin rudalics <rudalics@gmx.at> > CC: acm@muc.de, 16526@debbugs.gnu.org > > > More accurately, end-of-buffer calls recenter, which needs to compute > > where to put window-start, which requires Emacs to examine the text > > before point. As part of this examination, we invoke functions that > > simulate display, and those trigger JIT Lock, whose fontification > > function starts the madness. > > This doesn't match my observations. With my shortened scenario > > (progn > (setq scroll-conservatively 101) > (find-file (concat source-directory "src/xdisp.c")) > (end-of-buffer) > (sit-for 3)) > > there is no such problem. You are right, sorry. (I wasn't wrong, either: recenter does call the same find_defun_start around EOB, which is what I saw. But those calls are very few and aren't responsible for the slowdown. I also wasn't wrong about point being at EOB, see below. But I described what happens incorrectly.) Here's what I see in the debugger: After beginning-of-buffer jumps to point-min, redisplay kicks in. Since scroll-conservatively is set to a large value, redisplay first tries to see whether it can bring point into view by scrolling the window as little as possible. It calls try_scrolling, which at some point (around line 15000) tries to see whether the new location of point is close enough to the current window start. It does so by calling move_it_to, which simulates the display. While doing so, move_it_to hits a portion of text with font-lock properties, and calls JIT Lock to fontify them. And here's where things go awry: For some reason, the CC Mode fontification code decides it needs to scan the buffer backwards, starting from EOB. So it goes temporarily to EOB (this is why I saw point being there), and scans all the way back, I think in this loop from c-append-lower-brace-pair-to-state-cache, which is called with its first argument FROM set to EOB: ;; In the next pair of nested loops, the inner one moves back past a ;; pair of (mis-)matching parens or brackets; the outer one moves ;; back over a sequence of unmatched close brace/paren/bracket each ;; time round. (while (progn (c-safe (while (and (setq ce (scan-lists bra -1 -1)) ; back past )/]/}; might signal (setq bra (scan-lists ce -1 1)) ; back past (/[/{; might signal (or (> bra here) ;(> ce here) (and (< ce here) (or (not (eq (char-after bra) ?\{)) (and (goto-char bra) (c-beginning-of-macro) (< (point) macro-start-or-from)))))))) (and ce (< ce bra))) (setq bra ce)) ; If we just backed over an unbalanced closing ; brace, ignore it. This loop takes a lot of time, of course, and is a waste of time, since eventually try_scrolling comes to the correct conclusion that scrolling is impossible, and instead recenters at BOB. Why does CC Mode decide to go from EOB backwards, I don't know; presumably, this is decided by c-parse-state-get-strategy as part of c-parse-state-1. For the record, below is the full C and Lisp backtrace I obtained when c-append-lower-brace-pair-to-state-cache jumps to the EOB, which in Lisp happens here: (save-excursion (save-restriction (let* (new-cons (cache-pos (c-state-cache-top-lparen)) ; might be nil. (macro-start-or-from (progn (goto-char from) <<<<<<<<<<<<<<<<<<<<<<<<<<< (c-beginning-of-macro) (point))) (bra ; Position of "{". ;; Don't start scanning in the middle of a CPP construct unless ;; it contains HERE - these constructs, in Emacs, are "commented ;; out" with category properties. (if (eq (c-get-char-property macro-start-or-from 'category) 'c-cpp-delimiter) macro-start-or-from from)) ce) ; Position of "}" I hope this information will allow Alan to find the culprit and solve the problem. ============================================================================= Hardware watchpoint 4: -location current_buffer->pt Old value = 1617 New value = 947778 0x011df59f in temp_set_point_both ( buffer=0x380be00 <__register_frame_info+58768896>, charpos=947778, bytepos=947778) at intervals.c:1789 1789 SET_BUF_PT_BOTH (buffer, charpos, bytepos); (gdb) bt #0 0x011df59f in temp_set_point_both ( buffer=0x380be00 <__register_frame_info+58768896>, charpos=947778, bytepos=947778) at intervals.c:1789 #1 0x011dfd99 in set_point_both (charpos=947778, bytepos=947778) at intervals.c:2045 #2 0x011df60a in set_point (charpos=947778) at intervals.c:1807 #3 0x011700fd in Fgoto_char (position=...) at editfns.c:239 #4 0x011820e2 in eval_sub (form=...) at eval.c:2176 #5 0x0117dc49 in Fprogn (body=...) at eval.c:459 #6 0x01181e50 in eval_sub (form=...) at eval.c:2124 #7 0x0117edea in FletX (args=...) at eval.c:872 #8 0x01181e50 in eval_sub (form=...) at eval.c:2124 #9 0x0117dc49 in Fprogn (body=...) at eval.c:459 #10 0x01176cc2 in Fsave_restriction (body=...) at editfns.c:3415 #11 0x01181e50 in eval_sub (form=...) at eval.c:2124 #12 0x0117dc49 in Fprogn (body=...) at eval.c:459 #13 0x0117161e in Fsave_excursion (args=...) at editfns.c:941 #14 0x01181e50 in eval_sub (form=...) at eval.c:2124 #15 0x0117dc49 in Fprogn (body=...) at eval.c:459 #16 0x01183f33 in funcall_lambda (fun=..., nargs=2, arg_vector=0x886db0) at eval.c:3033 #17 0x01183911 in apply_lambda (fun=..., args=...) at eval.c:2915 #18 0x0118244d in eval_sub (form=...) at eval.c:2251 #19 0x0117d9d4 in Fif (args=...) at eval.c:410 #20 0x01181e50 in eval_sub (form=...) at eval.c:2124 #21 0x0117dc49 in Fprogn (body=...) at eval.c:459 #22 0x0117db99 in Fcond (args=...) at eval.c:437 #23 0x01181e50 in eval_sub (form=...) at eval.c:2124 #24 0x0117dc49 in Fprogn (body=...) at eval.c:459 #25 0x0117ef6b in FletX (args=...) at eval.c:897 #26 0x01181e50 in eval_sub (form=...) at eval.c:2124 #27 0x0117dc49 in Fprogn (body=...) at eval.c:459 #28 0x01183f33 in funcall_lambda (fun=..., nargs=0, arg_vector=0x887310) at eval.c:3033 #29 0x01183911 in apply_lambda (fun=..., args=...) at eval.c:2915 #30 0x0118244d in eval_sub (form=...) at eval.c:2251 #31 0x0117dc49 in Fprogn (body=...) at eval.c:459 #32 0x01181e50 in eval_sub (form=...) at eval.c:2124 #33 0x0117fb6a in Funwind_protect (args=...) at eval.c:1206 #34 0x01181e50 in eval_sub (form=...) at eval.c:2124 #35 0x0117dc49 in Fprogn (body=...) at eval.c:459 #36 0x0117ef6b in FletX (args=...) at eval.c:897 #37 0x01181e50 in eval_sub (form=...) at eval.c:2124 #38 0x0117fb6a in Funwind_protect (args=...) at eval.c:1206 #39 0x01181e50 in eval_sub (form=...) at eval.c:2124 #40 0x0117dc49 in Fprogn (body=...) at eval.c:459 #41 0x0117da92 in Fif (args=...) at eval.c:411 #42 0x01181e50 in eval_sub (form=...) at eval.c:2124 #43 0x0117dc49 in Fprogn (body=...) at eval.c:459 #44 0x01181e50 in eval_sub (form=...) at eval.c:2124 #45 0x0117fb6a in Funwind_protect (args=...) at eval.c:1206 #46 0x01181e50 in eval_sub (form=...) at eval.c:2124 #47 0x0117dd09 in Fprog1 (args=...) at eval.c:491 #48 0x01181e50 in eval_sub (form=...) at eval.c:2124 #49 0x0117dc49 in Fprogn (body=...) at eval.c:459 #50 0x0117f401 in Flet (args=...) at eval.c:967 #51 0x01181e50 in eval_sub (form=...) at eval.c:2124 #52 0x0117dc49 in Fprogn (body=...) at eval.c:459 #53 0x01183f33 in funcall_lambda (fun=..., nargs=0, arg_vector=0x887f28) at eval.c:3033 #54 0x0118371d in Ffuncall (nargs=1, args=0x887f24) at eval.c:2867 #55 0x011c4bc3 in exec_byte_code (bytestr=..., vector=..., maxdepth=..., args_template=..., nargs=0, args=0x0) at bytecode.c:919 #56 0x01183fc8 in funcall_lambda (fun=..., nargs=1, arg_vector=0x3936595 <__register_frame_info+59991445>) at eval.c:3040 #57 0x01183644 in Ffuncall (nargs=2, args=0x888264) at eval.c:2855 #58 0x011c4bc3 in exec_byte_code (bytestr=..., vector=..., maxdepth=..., args_template=..., nargs=0, args=0x0) at bytecode.c:919 #59 0x01183fc8 in funcall_lambda (fun=..., nargs=3, arg_vector=0x1317efd <pure+652573>) at eval.c:3040 #60 0x01183644 in Ffuncall (nargs=4, args=0x8885b4) at eval.c:2855 #61 0x011c4bc3 in exec_byte_code (bytestr=..., vector=..., maxdepth=..., args_template=..., nargs=0, args=0x0) at bytecode.c:919 #62 0x01183fc8 in funcall_lambda (fun=..., nargs=3, arg_vector=0x1317555 <pure+650101>) at eval.c:3040 #63 0x01183644 in Ffuncall (nargs=4, args=0x8888f4) at eval.c:2855 #64 0x011c4bc3 in exec_byte_code (bytestr=..., vector=..., maxdepth=..., args_template=..., nargs=0, args=0x0) at bytecode.c:919 #65 0x01183fc8 in funcall_lambda (fun=..., nargs=3, arg_vector=0x51d1bfd) at eval.c:3040 #66 0x01183644 in Ffuncall (nargs=4, args=0x888c34) at eval.c:2855 #67 0x011c4bc3 in exec_byte_code (bytestr=..., vector=..., maxdepth=..., args_template=..., nargs=0, args=0x0) at bytecode.c:919 #68 0x01183fc8 in funcall_lambda (fun=..., nargs=2, arg_vector=0x1317155 <pure+649077>) at eval.c:3040 #69 0x01183644 in Ffuncall (nargs=3, args=0x889098) at eval.c:2855 #70 0x011829aa in funcall_nil (nargs=3, args=0x889098) at eval.c:2357 #71 0x01182dbf in run_hook_with_args (nargs=3, args=0x889098, funcall=0x1182992 <funcall_nil>) at eval.c:2542 #72 0x01182a21 in Frun_hook_with_args (nargs=3, args=0x889098) at eval.c:2403 #73 0x0118330a in Ffuncall (nargs=4, args=0x889094) at eval.c:2787 #74 0x011c4bc3 in exec_byte_code (bytestr=..., vector=..., maxdepth=..., args_template=..., nargs=0, args=0x8893e4) at bytecode.c:919 #75 0x01183bf2 in funcall_lambda (fun=..., nargs=0, arg_vector=0x8893e4) at eval.c:2974 #76 0x01183644 in Ffuncall (nargs=1, args=0x8893e0) at eval.c:2855 #77 0x01181fe4 in eval_sub (form=...) at eval.c:2148 #78 0x0118025e in internal_lisp_condition_case (var=..., bodyform=..., handlers=...) at eval.c:1314 #79 0x011c5af4 in exec_byte_code (bytestr=..., vector=..., maxdepth=..., args_template=..., nargs=2, args=0x8898c4) at bytecode.c:1169 #80 0x01183bf2 in funcall_lambda (fun=..., nargs=2, arg_vector=0x8898bc) at eval.c:2974 #81 0x01183644 in Ffuncall (nargs=3, args=0x8898b8) at eval.c:2855 #82 0x011c4bc3 in exec_byte_code (bytestr=..., vector=..., maxdepth=..., args_template=..., nargs=1, args=0x889c58) at bytecode.c:919 #83 0x01183bf2 in funcall_lambda (fun=..., nargs=1, arg_vector=0x889c54) at eval.c:2974 #84 0x01183644 in Ffuncall (nargs=2, args=0x889c50) at eval.c:2855 #85 0x011806bb in internal_condition_case_n (bfun=0x11830e4 <Ffuncall>, nargs=2, args=0x889c50, handlers=..., hfun=0x1026dfa <safe_eval_handler>) at eval.c:1427 #86 0x01026f19 in safe_call (nargs=2, func=...) at xdisp.c:2563 #87 0x01026f56 in safe_call1 (fn=..., arg=...) at xdisp.c:2579 #88 0x0102a1d5 in handle_fontified_prop (it=0x88d2fc) at xdisp.c:3756 #89 0x010293a3 in handle_stop (it=0x88d2fc) at xdisp.c:3320 #90 0x010359e6 in next_element_from_buffer (it=0x88d2fc) at xdisp.c:8077 #91 0x010325b4 in get_next_display_element (it=0x88d2fc) at xdisp.c:6732 #92 0x010364d4 in move_it_in_display_line_to (it=0x88d2fc, to_charpos=949978, to_x=0, op=(MOVE_TO_X | MOVE_TO_POS)) at xdisp.c:8412 #93 0x01038443 in move_it_to (it=0x88d2fc, to_charpos=949978, to_x=0, to_y=1600, to_vpos=-1, op=11) at xdisp.c:8936 #94 0x0104798f in try_scrolling (window=..., just_this_one_p=0, arg_scroll_conservatively=101, scroll_step=0, temp_scroll_step=0, last_line_misfit=0) at xdisp.c:15016 #95 0x0104bb7b in redisplay_window (window=..., just_this_one_p=false) at xdisp.c:16119 #96 0x01044bf1 in redisplay_window_0 (window=...) at xdisp.c:14056 #97 0x01180479 in internal_condition_case_1 ( bfun=0x1044bbb <redisplay_window_0>, arg=..., handlers=..., hfun=0x1044b97 <redisplay_window_error>) at eval.c:1369 #98 0x01044b7c in redisplay_windows (window=...) at xdisp.c:14036 #99 0x01043b49 in redisplay_internal () at xdisp.c:13635 #100 0x0103ca92 in resize_echo_area_exactly () at xdisp.c:10559 #101 0x010f622b in command_loop_1 () at keyboard.c:1571 #102 0x01180366 in internal_condition_case (bfun=0x10f5b5b <command_loop_1>, handlers=..., hfun=0x10f53c7 <cmd_error>) at eval.c:1345 #103 0x010f5811 in command_loop_2 (ignore=...) at keyboard.c:1170 #104 0x0117f913 in internal_catch (tag=..., func=0x10f57ed <command_loop_2>, arg=...) at eval.c:1109 #105 0x010f57c9 in command_loop () at keyboard.c:1149 #106 0x010f4f63 in recursive_edit_1 () at keyboard.c:777 #107 0x010f5120 in Frecursive_edit () at keyboard.c:841 #108 0x010f32ff in main (argc=2, argv=0xe51ff8) at emacs.c:1643 Lisp Backtrace: "goto-char" (0x886820) "progn" (0x88696c) "let*" (0x886a8c) "save-restriction" (0x886bac) "save-excursion" (0x886ccc) "c-append-lower-brace-pair-to-state-cache" (0x886db0) "if" (0x886fac) "cond" (0x8870dc) "let*" (0x88722c) "c-parse-state-1" (0x887310) "progn" (0x8874fc) "unwind-protect" (0x8875ec) "let*" (0x88773c) "unwind-protect" (0x88782c) "if" (0x88794c) "progn" (0x887a3c) "unwind-protect" (0x887b2c) "prog1" (0x887c2c) "let" (0x887dbc) "c-parse-state" (0x887f28) "c-font-lock-complex-decl-prepare" (0x888268) "font-lock-fontify-keywords-region" (0x8885b8) "font-lock-default-fontify-region" (0x8888f8) "c-font-lock-fontify-region" (0x888c38) "font-lock-fontify-region" (0x88909c) "run-hook-with-args" (0x889098) 0x37cc9b0 PVEC_COMPILED "funcall" (0x8893e0) "jit-lock-fontify-now" (0x8898bc) "jit-lock-function" (0x889c54) "redisplay_internal (C function)" (0x153de1c) ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-01-26 17:20 ` Eli Zaretskii @ 2014-01-26 20:43 ` Alan Mackenzie 2014-01-27 8:21 ` martin rudalics ` (2 more replies) 2014-01-27 8:20 ` martin rudalics 1 sibling, 3 replies; 93+ messages in thread From: Alan Mackenzie @ 2014-01-26 20:43 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 16526 Hi, Eli. On Sun, Jan 26, 2014 at 07:20:27PM +0200, Eli Zaretskii wrote: > You are right, sorry. (I wasn't wrong, either: recenter does call the > same find_defun_start around EOB, which is what I saw. But those > calls are very few and aren't responsible for the slowdown. I also > wasn't wrong about point being at EOB, see below. But I described > what happens incorrectly.) > Here's what I see in the debugger: > After beginning-of-buffer jumps to point-min, redisplay kicks in. > Since scroll-conservatively is set to a large value, redisplay first > tries to see whether it can bring point into view by scrolling the > window as little as possible. It calls try_scrolling, which at some > point (around line 15000) tries to see whether the new location of > point is close enough to the current window start. It does so by > calling move_it_to, which simulates the display. While doing so, > move_it_to hits a portion of text with font-lock properties, and calls > JIT Lock to fontify them. > And here's where things go awry: For some reason, the CC Mode > fontification code decides it needs to scan the buffer backwards, > starting from EOB. The @dfn{state cache}, a list of certain brace/paren/bracket positions around some position, is set for a position near EOB. With the switch to a different position, CC Mode tweaks the state cache rather than calculating it anew starting at BOB. When the new position is nearer BOB, the code searches backwards for the appropriate braces. However, it shouldn't be scanning the entire buffer backwards. There is clearly a bug here. > So it goes temporarily to EOB (this is why I saw point being there), > and scans all the way back, I think in this loop from > c-append-lower-brace-pair-to-state-cache, which is called with its > first argument FROM set to EOB: > ;; In the next pair of nested loops, the inner one moves back past a > ;; pair of (mis-)matching parens or brackets; the outer one moves > ;; back over a sequence of unmatched close brace/paren/bracket each > ;; time round. > (while > (progn > (c-safe > (while > (and (setq ce (scan-lists bra -1 -1)) ; back past )/]/}; might signal > (setq bra (scan-lists ce -1 1)) ; back past (/[/{; might signal > (or (> bra here) ;(> ce here) > (and > (< ce here) > (or (not (eq (char-after bra) ?\{)) > (and (goto-char bra) > (c-beginning-of-macro) > (< (point) macro-start-or-from)))))))) > (and ce (< ce bra))) > (setq bra ce)) ; If we just backed over an unbalanced closing > ; brace, ignore it. The backward scan-lists calls will be causing continual forward searches from BOB in syntax.c, every time the backward scan hits a comment ender. > This loop takes a lot of time, of course, and is a waste of time, > since eventually try_scrolling comes to the correct conclusion that > scrolling is impossible, and instead recenters at BOB. > Why does CC Mode decide to go from EOB backwards, I don't know; > presumably, this is decided by c-parse-state-get-strategy as part of > c-parse-state-1. Yes. There is a bug here. I have a strong suspicion where. [ .... ] > I hope this information will allow Alan to find the culprit and solve > the problem. Yes indeed, thanks. But I'm not going to be able to resolve it in a scale of hours. It's going to be days. Sorry! -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-01-26 20:43 ` Alan Mackenzie @ 2014-01-27 8:21 ` martin rudalics 2014-01-29 21:52 ` Alan Mackenzie [not found] ` <52E61704.6050807@gmx.at> 2 siblings, 0 replies; 93+ messages in thread From: martin rudalics @ 2014-01-27 8:21 UTC (permalink / raw) To: Alan Mackenzie; +Cc: 16526 > The @dfn{state cache}, a list of certain brace/paren/bracket positions > around some position, is set for a position near EOB. With the switch to > a different position, CC Mode tweaks the state cache rather than > calculating it anew starting at BOB. When the new position is nearer > BOB, the code searches backwards for the appropriate braces. However, it > shouldn't be scanning the entire buffer backwards. There is clearly a > bug here. In my scenario `end-of-buffer' should already have produced the complete state cache. How else would you have been able to fontify code near EOB correctly? > The backward scan-lists calls will be causing continual forward searches > from BOB in syntax.c, every time the backward scan hits a comment ender. IIUC now any call to `forward-comment' with a negative argument will automatically go to BOB unless it's already there. How else could it determine that it's not called from a position within a comment? So if you decide to bind `open-paren-in-column-0-is-defun-start' to nil, then why don't you build the state cache anew from BOB? In any case, please provide an option say `c-open-paren-in-column-0-is-defun-start' which people can set to avoid those scans. The doc-string should mention that things like Michael's commented out code are handled correctly iff this option is nil and that long delays while working with c-mode can be sometimes avoided by setting this option to t. The default value could be obviously nil. martin ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-01-26 20:43 ` Alan Mackenzie 2014-01-27 8:21 ` martin rudalics @ 2014-01-29 21:52 ` Alan Mackenzie 2014-01-30 17:16 ` Eli Zaretskii [not found] ` <52E61704.6050807@gmx.at> 2 siblings, 1 reply; 93+ messages in thread From: Alan Mackenzie @ 2014-01-29 21:52 UTC (permalink / raw) To: Eli Zaretskii, martin rudalics; +Cc: 16526 Hello, Eli, hello, Martin. On Sun, Jan 26, 2014 at 08:43:10PM +0000, Alan Mackenzie wrote: > On Sun, Jan 26, 2014 at 07:20:27PM +0200, Eli Zaretskii wrote: > > You are right, sorry. (I wasn't wrong, either: recenter does call the > > same find_defun_start around EOB, which is what I saw. But those > > calls are very few and aren't responsible for the slowdown. I also > > wasn't wrong about point being at EOB, see below. But I described > > what happens incorrectly.) > > Here's what I see in the debugger: > > After beginning-of-buffer jumps to point-min, redisplay kicks in. > > Since scroll-conservatively is set to a large value, redisplay first > > tries to see whether it can bring point into view by scrolling the > > window as little as possible. It calls try_scrolling, which at some > > point (around line 15000) tries to see whether the new location of > > point is close enough to the current window start. It does so by > > calling move_it_to, which simulates the display. While doing so, > > move_it_to hits a portion of text with font-lock properties, and calls > > JIT Lock to fontify them. > > And here's where things go awry: For some reason, the CC Mode > > fontification code decides it needs to scan the buffer backwards, > > starting from EOB. > The @dfn{state cache}, a list of certain brace/paren/bracket positions > around some position, is set for a position near EOB. With the switch to > a different position, CC Mode tweaks the state cache rather than > calculating it anew starting at BOB. When the new position is nearer > BOB, the code searches backwards for the appropriate braces. However, it > shouldn't be scanning the entire buffer backwards. There is clearly a > bug here. > > So it goes temporarily to EOB (this is why I saw point being there), > > and scans all the way back, I think in this loop from > > c-append-lower-brace-pair-to-state-cache, which is called with its > > first argument FROM set to EOB: > > ;; In the next pair of nested loops, the inner one moves back past a > > ;; pair of (mis-)matching parens or brackets; the outer one moves > > ;; back over a sequence of unmatched close brace/paren/bracket each > > ;; time round. > > (while > > (progn > > (c-safe > > (while > > (and (setq ce (scan-lists bra -1 -1)) ; back past )/]/}; might signal > > (setq bra (scan-lists ce -1 1)) ; back past (/[/{; might signal > > (or (> bra here) ;(> ce here) > > (and > > (< ce here) > > (or (not (eq (char-after bra) ?\{)) > > (and (goto-char bra) > > (c-beginning-of-macro) > > (< (point) macro-start-or-from)))))))) > > (and ce (< ce bra))) > > (setq bra ce)) ; If we just backed over an unbalanced closing > > ; brace, ignore it. > The backward scan-lists calls will be causing continual forward searches > from BOB in syntax.c, every time the backward scan hits a comment ender. > > This loop takes a lot of time, of course, and is a waste of time, > > since eventually try_scrolling comes to the correct conclusion that > > scrolling is impossible, and instead recenters at BOB. > > Why does CC Mode decide to go from EOB backwards, I don't know; > > presumably, this is decided by c-parse-state-get-strategy as part of > > c-parse-state-1. > Yes. There is a bug here. I have a strong suspicion where. > [ .... ] > > I hope this information will allow Alan to find the culprit and solve > > the problem. > Yes indeed, thanks. But I'm not going to be able to resolve it in a > scale of hours. It's going to be days. Sorry! OK, here is a rough patch (smooth version to follow if it's any good), which attempts to solve the problem by not calling c-append-lower-brace-pair-to-state-cache in the pertinent circumstances. Please try it out and let me know if it solves the problem (I still can't reproduce the massive slowdown myself). diff -r d6064f65b0a1 cc-engine.el --- a/cc-engine.el Sun Jan 19 12:09:59 2014 +0000 +++ b/cc-engine.el Wed Jan 29 21:17:50 2014 +0000 @@ -2556,6 +2556,8 @@ ;; o - ('forward START-POINT) - scan forward from START-POINT, ;; which is not less than the highest position in `c-state-cache' below here. ;; o - ('backward nil) - scan backwards (from HERE). + ;; o - ('back-and-forward START-POINT) - like 'forward, but when HERE is earlier + ;; than GOOD-POS. ;; o - ('IN-LIT nil) - point is inside the literal containing point-min. (let ((cache-pos (c-get-cache-scan-pos here)) ; highest position below HERE in cache (or 1) strategy ; 'forward, 'backward, or 'IN-LIT. @@ -2570,9 +2572,10 @@ ((< (- good-pos here) (- here cache-pos)) ; FIXME!!! ; apply some sort of weighting. (setq strategy 'backward)) (t - (setq strategy 'forward + (setq strategy 'back-and-forward start-point cache-pos))) - (list strategy (and (eq strategy 'forward) start-point)))) + (list strategy ;(and (eq strategy 'forward) + start-point)));) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -2857,7 +2860,7 @@ ;; adjust it to get outside a string/comment. (Sorry about this! The code ;; needs to be FAST). ;; - ;; Return a list (GOOD-POS SCAN-BACK-POS PPS-STATE), where + ;; Return a list (GOOD-POS SCAN-BACK-POS PPS-STATE), where FIXME!!! ;; o - GOOD-POS is a position where the new value `c-state-cache' is known ;; to be good (we aim for this to be as high as possible); ;; o - SCAN-BACK-POS, if not nil, indicates there may be a brace pair @@ -2892,6 +2895,7 @@ pos upper-lim ; ,beyond which `c-state-cache' entries are removed scan-back-pos + cons-separated pair-beg pps-point-state target-depth) ;; Remove entries beyond HERE. Also remove any entries inside @@ -2913,7 +2917,8 @@ (consp (car c-state-cache)) (> (cdar c-state-cache) upper-lim)) (setcar c-state-cache (caar c-state-cache)) - (setq scan-back-pos (car c-state-cache))) + (setq scan-back-pos (car c-state-cache) + cons-separated t)) ;; The next loop jumps forward out of a nested level of parens each ;; time round; the corresponding elements in `c-state-cache' are @@ -2986,7 +2991,8 @@ (setq c-state-cache (cons (cons pair-beg pos) c-state-cache))) - (list pos scan-back-pos pps-state))))) + ;(when (< pos scan-back-pos) (setq scan-back-pos nil)) ; 2014-01-26 FIXME!!! + (list pos scan-back-pos pps-state cons-separated))))) (defun c-remove-stale-state-cache-backwards (here) ;; Strip stale elements of `c-state-cache' by moving backwards through the @@ -3271,6 +3277,7 @@ ; are no open parens/braces between it and HERE. bopl-state res + cons-separated scan-backward-pos scan-forward-p) ; used for 'backward. ;; If POINT-MIN has changed, adjust the cache (unless (= (point-min) c-state-point-min) @@ -3283,13 +3290,15 @@ ;; SCAN! (cond - ((eq strategy 'forward) + ((memq strategy '(forward back-and-forward)) ;(eq strategy 'forward) (setq res (c-remove-stale-state-cache start-point here here-bopl)) (setq cache-pos (car res) scan-backward-pos (cadr res) - bopl-state (car (cddr res))) ; will be nil if (< here-bopl + bopl-state (car (cddr res)) ; will be nil if (< here-bopl ; start-point) - (if scan-backward-pos + cons-separated (car (cdddr res))) + (if (and scan-backward-pos + (or cons-separated (eq strategy 'forward))) ;scan-backward-pos (c-append-lower-brace-pair-to-state-cache scan-backward-pos here)) (setq good-pos (c-append-to-state-cache cache-pos here)) -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-01-29 21:52 ` Alan Mackenzie @ 2014-01-30 17:16 ` Eli Zaretskii 2014-01-31 20:00 ` Alan Mackenzie 0 siblings, 1 reply; 93+ messages in thread From: Eli Zaretskii @ 2014-01-30 17:16 UTC (permalink / raw) To: Alan Mackenzie; +Cc: 16526 > Date: Wed, 29 Jan 2014 21:52:40 +0000 > Cc: 16526@debbugs.gnu.org > From: Alan Mackenzie <acm@muc.de> > > OK, here is a rough patch (smooth version to follow if it's any good), > which attempts to solve the problem by not calling > c-append-lower-brace-pair-to-state-cache in the pertinent circumstances. > Please try it out and let me know if it solves the problem It takes about 3 sec here, so I think it does solve the problem. > (I still can't reproduce the massive slowdown myself). Did you try to configure like I've shown and rebuild? ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-01-30 17:16 ` Eli Zaretskii @ 2014-01-31 20:00 ` Alan Mackenzie 2014-01-31 20:16 ` Eli Zaretskii 0 siblings, 1 reply; 93+ messages in thread From: Alan Mackenzie @ 2014-01-31 20:00 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 16526 Hi, Eli. On Thu, Jan 30, 2014 at 07:16:27PM +0200, Eli Zaretskii wrote: > > Date: Wed, 29 Jan 2014 21:52:40 +0000 > > Cc: 16526@debbugs.gnu.org > > From: Alan Mackenzie <acm@muc.de> > > OK, here is a rough patch (smooth version to follow if it's any good), > > which attempts to solve the problem by not calling > > c-append-lower-brace-pair-to-state-cache in the pertinent circumstances. > > Please try it out and let me know if it solves the problem > It takes about 3 sec here, so I think it does solve the problem. > > (I still can't reproduce the massive slowdown myself). > Did you try to configure like I've shown and rebuild? Sorry, no I hadn't. I wasn't paying enough attention when I read that post of yours. I've just tried it now, and with the unoptimised and instrumented version just created, using the unpatched cc-engine.elc, Martin's recipe takes me ~70 seconds. With my patch, it takes ~13 seconds. I think you commented somewhere that it would be a good idea to test on such a build "any change which might affect redisplay". That might be so, but how should one know which changes might do this? Binding open-paren-in-column-0-etc. to nil wouldn't have raised any alarm bells in this regard, since beginning-of-defun doesn't seem much connected with redisplay. -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-01-31 20:00 ` Alan Mackenzie @ 2014-01-31 20:16 ` Eli Zaretskii 0 siblings, 0 replies; 93+ messages in thread From: Eli Zaretskii @ 2014-01-31 20:16 UTC (permalink / raw) To: Alan Mackenzie; +Cc: 16526 > Date: Fri, 31 Jan 2014 20:00:01 +0000 > Cc: rudalics@gmx.at, 16526@debbugs.gnu.org > From: Alan Mackenzie <acm@muc.de> > > I think you commented somewhere that it would be a good idea to test on > such a build "any change which might affect redisplay". That might be > so, but how should one know which changes might do this? In your case, it's simple: any changes that affect font-lock, automatically affect redisplay, via JIT Lock. So I suggest always to do your testing of such changes in an unoptimized build. That is, when you finish development and start testing, do it in an unoptimized build. Thanks. ^ permalink raw reply [flat|nested] 93+ messages in thread
[parent not found: <52E61704.6050807@gmx.at>]
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression [not found] ` <52E61704.6050807@gmx.at> @ 2014-01-27 14:49 ` Stefan Monnier [not found] ` <jwvvbx5fq2b.fsf-monnier+emacsbugs@gnu.org> ` (2 subsequent siblings) 3 siblings, 0 replies; 93+ messages in thread From: Stefan Monnier @ 2014-01-27 14:49 UTC (permalink / raw) To: martin rudalics; +Cc: Alan Mackenzie, 16526 > IIUC now any call to `forward-comment' with a negative argument will > automatically go to BOB unless it's already there. Actually, that should not always be the case, no. > How else could it determine that it's not called from a position > within a comment? In general, that is true, but back_comment tries to be more clever, e.g, when it scans backward over code like /* toto */ blabla /* titi */ it should not need to scan further than the end of line 1, since the "*/" there will tell it that the "/*" on line 3 can't be within another comment and is hence the one-true comment starter that matches the "*/" on line 3. Of course, reality is more complex because there are also strings and //...\n comments, but at least back_comment tries to avoid scanning from BOB when it can. I think it even tries hard enough to consciously prefer performance over correctness, so that it will incorrectly handle // hello /* there bogus code */ and will jump to "/*" thinking it jumped over a comment. > In any case, please provide an option say > `c-open-paren-in-column-0-is-defun-start' which people can set to avoid > those scans. The doc-string should mention that things like Michael's > commented out code are handled correctly iff this option is nil and that > long delays while working with c-mode can be sometimes avoided by > setting this option to t. The default value could be obviously nil. Another option is to put a syntax-table property on those rare open-paren-in-column-0-inside-comment-or-string, so that open-paren-in-column-0-is-defun-start still works properly. Stefan PS: And yes, back_comment should somehow make use of syntax-ppss-cache to avoid scanning from BOB. ^ permalink raw reply [flat|nested] 93+ messages in thread
[parent not found: <jwvvbx5fq2b.fsf-monnier+emacsbugs@gnu.org>]
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression [not found] ` <jwvvbx5fq2b.fsf-monnier+emacsbugs@gnu.org> @ 2014-01-27 17:25 ` martin rudalics [not found] ` <52E69695.5040703@gmx.at> 1 sibling, 0 replies; 93+ messages in thread From: martin rudalics @ 2014-01-27 17:25 UTC (permalink / raw) To: Stefan Monnier; +Cc: Alan Mackenzie, 16526 > In general, that is true, but back_comment tries to be more clever, e.g, > when it scans backward over code like > > /* toto */ > blabla > /* titi */ > > it should not need to scan further than the end of line 1, since the > "*/" there will tell it that the "/*" on line 3 can't be within > another comment and is hence the one-true comment starter that matches > the "*/" on line 3. I recall now. I tend to forget that C comments cannot be nested. > Another option is to put a syntax-table property on those rare > open-paren-in-column-0-inside-comment-or-string, so that > open-paren-in-column-0-is-defun-start still works properly. Wouldn't we then have to parse the entire buffer for strings and comments in order to detect these parens? More or less this would duplicate the effort of `syntax-ppss'. martin ^ permalink raw reply [flat|nested] 93+ messages in thread
[parent not found: <52E69695.5040703@gmx.at>]
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression [not found] ` <52E69695.5040703@gmx.at> @ 2014-01-28 0:16 ` Stefan Monnier 0 siblings, 0 replies; 93+ messages in thread From: Stefan Monnier @ 2014-01-28 0:16 UTC (permalink / raw) To: martin rudalics; +Cc: Alan Mackenzie, 16526 >> Another option is to put a syntax-table property on those rare >> open-paren-in-column-0-inside-comment-or-string, so that >> open-paren-in-column-0-is-defun-start still works properly. > Wouldn't we then have to parse the entire buffer for strings and > comments in order to detect these parens? More or less this would > duplicate the effort of `syntax-ppss'. IIUC CC-mode does do such scanning to place syntax-table properties on various elements (it should do it from syntax-propertize-function, but for various reasons it does it at various other places instead, in piecemeal fashion). So it would just be adding one more element to find and mark. Stefan ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression [not found] ` <52E61704.6050807@gmx.at> 2014-01-27 14:49 ` Stefan Monnier [not found] ` <jwvvbx5fq2b.fsf-monnier+emacsbugs@gnu.org> @ 2014-01-29 22:36 ` Alan Mackenzie [not found] ` <20140129223626.GD3092@acm.acm> 3 siblings, 0 replies; 93+ messages in thread From: Alan Mackenzie @ 2014-01-29 22:36 UTC (permalink / raw) To: martin rudalics; +Cc: 16526 Hi, Martin. On Mon, Jan 27, 2014 at 09:21:24AM +0100, martin rudalics wrote: > > The @dfn{state cache}, a list of certain brace/paren/bracket positions > > around some position, is set for a position near EOB. With the switch to > > a different position, CC Mode tweaks the state cache rather than > > calculating it anew starting at BOB. When the new position is nearer > > BOB, the code searches backwards for the appropriate braces. However, it > > shouldn't be scanning the entire buffer backwards. There is clearly a > > bug here. > In my scenario `end-of-buffer' should already have produced the complete > state cache. How else would you have been able to fontify code near EOB > correctly? The state cache contains not only a list of enclosing braces/brackets/parentheses but also any brace pair immediately preceding one of these things. So a typical state cache looks like: (4532 (4284 . 4526) 4278 (4131 . 4248)) (with a detailed explanation in cc-engine.el in the comment for `c-parse-state-1'). When c-parse-state is called at a position somewhat distant from the previous call, it modifies the state cache by crawling through the buffer rather than recalculating it from scratch. > > The backward scan-lists calls will be causing continual forward searches > > from BOB in syntax.c, every time the backward scan hits a comment ender. > IIUC now any call to `forward-comment' with a negative argument will > automatically go to BOB unless it's already there. How else could it > determine that it's not called from a position within a comment? I don't think this happens. back_comment (in syntax.c) assumes it starts outside a comment. > So if you decide to bind `open-paren-in-column-0-is-defun-start' to > nil, then why don't you build the state cache anew from BOB? The state cache has different values for different buffer positions. > In any case, please provide an option say > `c-open-paren-in-column-0-is-defun-start' which people can set to > avoid those scans. The doc-string should mention that things like > Michael's commented out code are handled correctly iff this option is > nil and that long delays while working with c-mode can be sometimes > avoided by setting this option to t. The default value could be > obviously nil. I'm hoping that the (rough) patch in one of my other emails from this evening will have solved the bug, so that playing around with open-paren-in-column-0-etc. won't be needed. As a matter of interest, with my patch applied, running your recipe on xdisp.c took me 4.4 seconds (including the (sit-for 3)). > martin -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 93+ messages in thread
[parent not found: <20140129223626.GD3092@acm.acm>]
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression [not found] ` <20140129223626.GD3092@acm.acm> @ 2014-01-30 7:37 ` martin rudalics 2014-01-30 13:47 ` martin rudalics [not found] ` <52EA57D6.5080403@gmx.at> 0 siblings, 2 replies; 93+ messages in thread From: martin rudalics @ 2014-01-30 7:37 UTC (permalink / raw) To: Alan Mackenzie; +Cc: 16526 > I don't think this happens. back_comment (in syntax.c) assumes it > starts outside a comment. Does it? >> In any case, please provide an option say >> `c-open-paren-in-column-0-is-defun-start' which people can set to >> avoid those scans. The doc-string should mention that things like >> Michael's commented out code are handled correctly iff this option is >> nil and that long delays while working with c-mode can be sometimes >> avoided by setting this option to t. The default value could be >> obviously nil. > > I'm hoping that the (rough) patch in one of my other emails from this > evening will have solved the bug, so that playing around with > open-paren-in-column-0-etc. won't be needed. > > As a matter of interest, with my patch applied, running your recipe on > xdisp.c took me 4.4 seconds (including the (sit-for 3)). Less than 8 seconds here which is quite remarkable. Unfortunately, I seem to have another problem now which makes `beginning-of-buffer' in xdisp.c extremely slow with my setup (~ 30 secs). Have to bisect my .emacs again ... Thanks so far, martin ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-01-30 7:37 ` martin rudalics @ 2014-01-30 13:47 ` martin rudalics [not found] ` <52EA57D6.5080403@gmx.at> 1 sibling, 0 replies; 93+ messages in thread From: martin rudalics @ 2014-01-30 13:47 UTC (permalink / raw) To: Alan Mackenzie; +Cc: 16526 Weird. With your patch on Windows I put into my .emacs these two lines (find-file (concat source-directory "src/xdisp.c")) (setq initial-frame-alist '((fullscreen . maximized))) and then switch to buffer xdisp.c. If I _now_ type <C-end> it takes at least 20 seconds. Can anyone reproduce that? With a non-maximized frame there's no such problem. And on Debian Gtk <C-end> takes less than 8 seconds here. martin ^ permalink raw reply [flat|nested] 93+ messages in thread
[parent not found: <52EA57D6.5080403@gmx.at>]
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression [not found] ` <52EA57D6.5080403@gmx.at> @ 2014-01-30 17:15 ` Eli Zaretskii 2014-01-30 18:58 ` martin rudalics [not found] ` <52EAA0C9.1090000@gmx.at> 0 siblings, 2 replies; 93+ messages in thread From: Eli Zaretskii @ 2014-01-30 17:15 UTC (permalink / raw) To: martin rudalics; +Cc: acm, 16526 > Date: Thu, 30 Jan 2014 14:47:02 +0100 > From: martin rudalics <rudalics@gmx.at> > Cc: 16526@debbugs.gnu.org > > Weird. With your patch on Windows I put into my .emacs these two lines > > (find-file (concat source-directory "src/xdisp.c")) > (setq initial-frame-alist '((fullscreen . maximized))) > > and then switch to buffer xdisp.c. If I _now_ type <C-end> it takes at > least 20 seconds. Can anyone reproduce that? It takes about 11 sec here. But reverting the patch doesn't change this timing, I still get 11 sec. ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-01-30 17:15 ` Eli Zaretskii @ 2014-01-30 18:58 ` martin rudalics [not found] ` <52EAA0C9.1090000@gmx.at> 1 sibling, 0 replies; 93+ messages in thread From: martin rudalics @ 2014-01-30 18:58 UTC (permalink / raw) To: Eli Zaretskii; +Cc: acm, 16526 > It takes about 11 sec here. But reverting the patch doesn't change > this timing, I still get 11 sec. But it does take longer with a maximized window? If so, do you have an explanation? martin ^ permalink raw reply [flat|nested] 93+ messages in thread
[parent not found: <52EAA0C9.1090000@gmx.at>]
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression [not found] ` <52EAA0C9.1090000@gmx.at> @ 2014-02-01 10:41 ` Eli Zaretskii 2014-02-02 13:18 ` martin rudalics ` (2 more replies) 0 siblings, 3 replies; 93+ messages in thread From: Eli Zaretskii @ 2014-02-01 10:41 UTC (permalink / raw) To: martin rudalics; +Cc: acm, 16526 > Date: Thu, 30 Jan 2014 19:58:17 +0100 > From: martin rudalics <rudalics@gmx.at> > CC: acm@muc.de, 16526@debbugs.gnu.org > > > It takes about 11 sec here. But reverting the patch doesn't change > > this timing, I still get 11 sec. > > But it does take longer with a maximized window? Yes, it does. > If so, do you have an explanation? Those 11 seconds are spent inside 'recenter', which is called by end-of-buffer: ;; If we went to a place in the middle of the buffer, ;; adjust it to the beginning of a line. (cond ((and arg (not (consp arg))) (forward-line 1)) ((and (eq (current-buffer) (window-buffer)) (> (point) (window-end nil t))) ;; If the end of the buffer is not already on the screen, ;; then scroll specially to put it near, but not at, the bottom. (overlay-recenter (point)) (recenter -3)))) <<<<<<<<<<<<<<<<<<<<<<<<<< Stepping through 'recenter', I see the following: . It treats GUI frames specially (and indeed, in "emacs -nw", I don't see this slowdown). The special handling is that it attempts to find the window-start point that corresponds to the -3 argument, by interpreting that argument as the number of pixels equivalent to 3 canonical-height lines. . To this end, 'recenter' calls move_it_vertically_backward with the -3 argument converted to pixels. move_it_vertically_backward then tries to find that place, by simulating display. . As part of the display simulation, jit-lock-function is called (because we hit a buffer position which has a non-nil 'fontified' property) with a single argument: buffer position 948757. This single call takes almost all of the 11 seconds. When the frame is not maximized, the window height is smaller, so 'recenter' moves back a smaller amount of pixels, and calls jit-lock-function at a different buffer position. That call takes only about 2 sec (still quite a lot, IMO). Perhaps Alan could explain why the CC Mode fontification takes such a long time for buffer position 948757. ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-02-01 10:41 ` Eli Zaretskii @ 2014-02-02 13:18 ` martin rudalics 2014-02-02 17:40 ` Alan Mackenzie [not found] ` <20140202174050.GA5365@acm.acm> 2 siblings, 0 replies; 93+ messages in thread From: martin rudalics @ 2014-02-02 13:18 UTC (permalink / raw) To: Eli Zaretskii; +Cc: acm, 16526 > When the frame is not maximized, the window height is smaller, so > 'recenter' moves back a smaller amount of pixels, and calls > jit-lock-function at a different buffer position. That call takes > only about 2 sec (still quite a lot, IMO). Thanks for the explanation. It would never have occurred to me that different window starts could cause such a difference in execution time. martin ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-02-01 10:41 ` Eli Zaretskii 2014-02-02 13:18 ` martin rudalics @ 2014-02-02 17:40 ` Alan Mackenzie [not found] ` <20140202174050.GA5365@acm.acm> 2 siblings, 0 replies; 93+ messages in thread From: Alan Mackenzie @ 2014-02-02 17:40 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 16526 Hello, Eli. On Sat, Feb 01, 2014 at 12:41:51PM +0200, Eli Zaretskii wrote: > > Date: Thu, 30 Jan 2014 19:58:17 +0100 > > From: martin rudalics <rudalics@gmx.at> > > CC: acm@muc.de, 16526@debbugs.gnu.org > > > It takes about 11 sec here. But reverting the patch doesn't change > > > this timing, I still get 11 sec. > > But it does take longer with a maximized window? > Yes, it does. > > If so, do you have an explanation? > Those 11 seconds are spent inside 'recenter', which is called by > end-of-buffer: > ;; If we went to a place in the middle of the buffer, > ;; adjust it to the beginning of a line. > (cond ((and arg (not (consp arg))) (forward-line 1)) > ((and (eq (current-buffer) (window-buffer)) > (> (point) (window-end nil t))) > ;; If the end of the buffer is not already on the screen, > ;; then scroll specially to put it near, but not at, the bottom. > (overlay-recenter (point)) > (recenter -3)))) <<<<<<<<<<<<<<<<<<<<<<<<<< > Stepping through 'recenter', I see the following: > . It treats GUI frames specially (and indeed, in "emacs -nw", I > don't see this slowdown). The special handling is that it > attempts to find the window-start point that corresponds to the -3 > argument, by interpreting that argument as the number of pixels > equivalent to 3 canonical-height lines. > . To this end, 'recenter' calls move_it_vertically_backward with the > -3 argument converted to pixels. move_it_vertically_backward then > tries to find that place, by simulating display. > . As part of the display simulation, jit-lock-function is called > (because we hit a buffer position which has a non-nil 'fontified' > property) with a single argument: buffer position 948757. This > single call takes almost all of the 11 seconds. > When the frame is not maximized, the window height is smaller, so > 'recenter' moves back a smaller amount of pixels, and calls > jit-lock-function at a different buffer position. That call takes > only about 2 sec (still quite a lot, IMO). > Perhaps Alan could explain why the CC Mode fontification takes such a > long time for buffer position 948757. No, sorry I can't explain it. Except that CC Mode will be scanning forward through the entire buffer once (hopefully only once) to get the "parse state" near EOB. On a normally optimised 24.3 build, M-x goto-char 948757 is taking me a little over a second. This is in a GUI frame in X Windows, maximised by clicking on the maximise button at the top right of the frame. On my non-optimised 24.3.50 build with tracing built in, the same action, M-x goto-char 948757 takes 9 seconds. In a non-maximised frame it takes 8 seconds. In this build, M-> takes ~2 seconds regardless of whether the frame is maximised or not. I can't explain this difference. I've committed my patch. I hope it clears up the bug (which I haven't yet closed) more or less satisfactorally. -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 93+ messages in thread
[parent not found: <20140202174050.GA5365@acm.acm>]
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression [not found] ` <20140202174050.GA5365@acm.acm> @ 2014-02-02 18:07 ` Eli Zaretskii 2014-02-02 19:20 ` Alan Mackenzie 0 siblings, 1 reply; 93+ messages in thread From: Eli Zaretskii @ 2014-02-02 18:07 UTC (permalink / raw) To: Alan Mackenzie; +Cc: 16526 > Date: Sun, 2 Feb 2014 17:40:50 +0000 > Cc: martin rudalics <rudalics@gmx.at>, 16526@debbugs.gnu.org > From: Alan Mackenzie <acm@muc.de> > > > Perhaps Alan could explain why the CC Mode fontification takes such a > > long time for buffer position 948757. > > No, sorry I can't explain it. Except that CC Mode will be scanning > forward through the entire buffer once (hopefully only once) to get the > "parse state" near EOB. Why can't it start from a position outside any function instead? > On a normally optimised 24.3 build, M-x goto-char 948757 is taking me a > little over a second. This is in a GUI frame in X Windows, maximised by > clicking on the maximise button at the top right of the frame. > > On my non-optimised 24.3.50 build with tracing built in, the same action, > M-x goto-char 948757 takes 9 seconds. In a non-maximised frame it takes > 8 seconds. In this build, M-> takes ~2 seconds regardless of whether the > frame is maximised or not. I can't explain this difference. These times are consistent with what I see. > I've committed my patch. I hope it clears up the bug (which I haven't > yet closed) more or less satisfactorally. Thanks. ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-02-02 18:07 ` Eli Zaretskii @ 2014-02-02 19:20 ` Alan Mackenzie 2014-02-02 20:53 ` Eli Zaretskii 0 siblings, 1 reply; 93+ messages in thread From: Alan Mackenzie @ 2014-02-02 19:20 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 16526 Hi, Eli. On Sun, Feb 02, 2014 at 08:07:25PM +0200, Eli Zaretskii wrote: > > Date: Sun, 2 Feb 2014 17:40:50 +0000 > > Cc: martin rudalics <rudalics@gmx.at>, 16526@debbugs.gnu.org > > From: Alan Mackenzie <acm@muc.de> > > > Perhaps Alan could explain why the CC Mode fontification takes such a > > > long time for buffer position 948757. > > No, sorry I can't explain it. Except that CC Mode will be scanning > > forward through the entire buffer once (hopefully only once) to get the > > "parse state" near EOB. > Why can't it start from a position outside any function instead? It used to do this, but this was leading to errors, particularly in C++ where, for example, people frequently write "namespace {" rather than putting the "{" on the next line in column 0. Even on xdisp.c, over 30,000 and almost 1Mb, the scan doesn't take that long - a little over a second on my 4 yo machine. -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-02-02 19:20 ` Alan Mackenzie @ 2014-02-02 20:53 ` Eli Zaretskii 2014-02-05 23:00 ` Alan Mackenzie 0 siblings, 1 reply; 93+ messages in thread From: Eli Zaretskii @ 2014-02-02 20:53 UTC (permalink / raw) To: Alan Mackenzie; +Cc: 16526 > Date: Sun, 2 Feb 2014 19:20:07 +0000 > Cc: rudalics@gmx.at, 16526@debbugs.gnu.org > From: Alan Mackenzie <acm@muc.de> > > Even on xdisp.c, over 30,000 and almost 1Mb, the scan doesn't take that > long - a little over a second on my 4 yo machine. Do you need help in identifying what takes 11 sec in the unoptimized build to traverse a few lines? ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-02-02 20:53 ` Eli Zaretskii @ 2014-02-05 23:00 ` Alan Mackenzie 2014-02-06 6:01 ` Eli Zaretskii 0 siblings, 1 reply; 93+ messages in thread From: Alan Mackenzie @ 2014-02-05 23:00 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 16526 Hello, Eli. On Sun, Feb 02, 2014 at 10:53:18PM +0200, Eli Zaretskii wrote: > > Date: Sun, 2 Feb 2014 19:20:07 +0000 > > Cc: rudalics@gmx.at, 16526@debbugs.gnu.org > > From: Alan Mackenzie <acm@muc.de> > > Even on xdisp.c, over 30,000 and almost 1Mb, the scan doesn't take that > > long - a little over a second on my 4 yo machine. > Do you need help in identifying what takes 11 sec in the unoptimized > build to traverse a few lines? Thanks for the offer. I really need to get down and spend a few hours investigating. I've elp'd CC Mode, and tried M-> (2 seconds) followed by <PgUp> (13 seconds), and it looks like c-append-lower-brace-pair-to-state-cache is taking up the time. It seems it is being called too often. Maybe. Maybe I'll pin it down at the weekend. -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-02-05 23:00 ` Alan Mackenzie @ 2014-02-06 6:01 ` Eli Zaretskii 2014-06-22 16:49 ` Eli Zaretskii 0 siblings, 1 reply; 93+ messages in thread From: Eli Zaretskii @ 2014-02-06 6:01 UTC (permalink / raw) To: Alan Mackenzie; +Cc: 16526 > Date: Wed, 5 Feb 2014 23:00:01 +0000 > Cc: rudalics@gmx.at, 16526@debbugs.gnu.org > From: Alan Mackenzie <acm@muc.de> > > > Do you need help in identifying what takes 11 sec in the unoptimized > > build to traverse a few lines? > > Thanks for the offer. I really need to get down and spend a few hours > investigating. I've elp'd CC Mode, and tried M-> (2 seconds) followed > by <PgUp> (13 seconds), and it looks like > c-append-lower-brace-pair-to-state-cache is taking up the time. It > seems it is being called too often. Maybe. > > Maybe I'll pin it down at the weekend. Thanks. ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-02-06 6:01 ` Eli Zaretskii @ 2014-06-22 16:49 ` Eli Zaretskii 2014-06-22 19:32 ` Alan Mackenzie 2014-06-25 21:32 ` Alan Mackenzie 0 siblings, 2 replies; 93+ messages in thread From: Eli Zaretskii @ 2014-06-22 16:49 UTC (permalink / raw) To: acm; +Cc: 16526-done > Date: Thu, 06 Feb 2014 08:01:32 +0200 > From: Eli Zaretskii <eliz@gnu.org> > Cc: rudalics@gmx.at, 16526@debbugs.gnu.org > > > Date: Wed, 5 Feb 2014 23:00:01 +0000 > > Cc: rudalics@gmx.at, 16526@debbugs.gnu.org > > From: Alan Mackenzie <acm@muc.de> > > > > > Do you need help in identifying what takes 11 sec in the unoptimized > > > build to traverse a few lines? > > > > Thanks for the offer. I really need to get down and spend a few hours > > investigating. I've elp'd CC Mode, and tried M-> (2 seconds) followed > > by <PgUp> (13 seconds), and it looks like > > c-append-lower-brace-pair-to-state-cache is taking up the time. It > > seems it is being called too often. Maybe. > > > > Maybe I'll pin it down at the weekend. > > Thanks. I hope Alan did something with this issue, or will in some near future. But either way, the original bug was fixed, so I'm closing this. ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-06-22 16:49 ` Eli Zaretskii @ 2014-06-22 19:32 ` Alan Mackenzie 2014-06-22 20:04 ` Eli Zaretskii 2014-06-25 21:32 ` Alan Mackenzie 1 sibling, 1 reply; 93+ messages in thread From: Alan Mackenzie @ 2014-06-22 19:32 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 16526 Hi, Eli. On Sun, Jun 22, 2014 at 07:49:29PM +0300, Eli Zaretskii wrote: > > Date: Thu, 06 Feb 2014 08:01:32 +0200 > > From: Eli Zaretskii <eliz@gnu.org> > > Cc: rudalics@gmx.at, 16526@debbugs.gnu.org > > > Date: Wed, 5 Feb 2014 23:00:01 +0000 > > > Cc: rudalics@gmx.at, 16526@debbugs.gnu.org > > > From: Alan Mackenzie <acm@muc.de> > > > > Do you need help in identifying what takes 11 sec in the unoptimized > > > > build to traverse a few lines? > > > Thanks for the offer. I really need to get down and spend a few hours > > > investigating. I've elp'd CC Mode, and tried M-> (2 seconds) followed > > > by <PgUp> (13 seconds), and it looks like > > > c-append-lower-brace-pair-to-state-cache is taking up the time. It > > > seems it is being called too often. Maybe. > > > Maybe I'll pin it down at the weekend. > > Thanks. > I hope Alan did something with this issue, or will in some near > future. I'm afraid I got bogged down, back in February. I've still got all my notes and attempted changes, so I'll see if I can't get something fixed for this. > But either way, the original bug was fixed, so I'm closing this. Thanks. -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-06-22 19:32 ` Alan Mackenzie @ 2014-06-22 20:04 ` Eli Zaretskii 0 siblings, 0 replies; 93+ messages in thread From: Eli Zaretskii @ 2014-06-22 20:04 UTC (permalink / raw) To: Alan Mackenzie; +Cc: 16526 > Date: Sun, 22 Jun 2014 19:32:58 +0000 > Cc: 16526@debbugs.gnu.org > From: Alan Mackenzie <acm@muc.de> > > I'm afraid I got bogged down, back in February. I've still got all my > notes and attempted changes, so I'll see if I can't get something fixed > for this. Thank you. ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-06-22 16:49 ` Eli Zaretskii 2014-06-22 19:32 ` Alan Mackenzie @ 2014-06-25 21:32 ` Alan Mackenzie 2014-06-26 2:51 ` Stefan Monnier 1 sibling, 1 reply; 93+ messages in thread From: Alan Mackenzie @ 2014-06-25 21:32 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 16526-done Hi, Eli. On Sun, Jun 22, 2014 at 07:49:29PM +0300, Eli Zaretskii wrote: > > Date: Thu, 06 Feb 2014 08:01:32 +0200 > > From: Eli Zaretskii <eliz@gnu.org> > > Cc: rudalics@gmx.at, 16526@debbugs.gnu.org > > > Date: Wed, 5 Feb 2014 23:00:01 +0000 > > > Cc: rudalics@gmx.at, 16526@debbugs.gnu.org > > > From: Alan Mackenzie <acm@muc.de> > > > > Do you need help in identifying what takes 11 sec in the unoptimized > > > > build to traverse a few lines? Just to recap what was taking 11 seconds. With xdisp.c revision 116189 newly loaded into an emacs -Q, do (goto-char 948757). This emacs was built with CFLAGS='-O0 -g3' and --enable-checking='yes,glyphs' Yes, I would like some help, please. [ From this point on, all my timings are with reference to my normal optimised build of Emacs 24.3 (though the version doesn't make any difference). ] I elp-instrument-package "c-" and elp-instrument-function "scan-lists". After the (goto-char 948757), my elp-results looks like this (with blank lines added for clarity): c-font-lock-fontify-region 6 1.12553871 0.187589785 scan-lists 2359 0.9151535670 0.0003879413 c-parse-state 200 0.8451750940 0.0042258754 c-parse-state-1 200 0.7929608409 0.0039648042 c-font-lock-enclosing-decls 6 0.7164836050 0.1194139341 c-append-lower-brace-pair-to-state-cache 4 0.7143309609 0.1785827402 c-font-lock-declarations 6 0.255113226 0.0425188710 c-find-decl-spots 6 0.255040271 0.0425067118 c-backward-over-enum-header 62 0.1797902729 0.0028998431 c-font-lock-complex-decl-prepare 6 0.0648537759 0.0108089626 Clearly c-append-lower-brace-pair-to-state-cache is problematic. I then timed each of the four calls of c-append-lower-...-cache. Three were rapid, one took 0.6977412700653076 seconds. I then zeroed in on the main loop (the only loop, really) and when I found it was hardly looping at all (a mere four calls of scan-lists altogether). I then timed _each_ individual call of scan-lists, and found that the call (scan-lists 947171 -1 1) took 0.6962041854858398 seconds. (947171 is just inside the closing brace of syms_of_xdisp, and the result of the scan is 919215, the function's opening brace.) How come this scan-lists is taking 0.7 seconds? When I call this from M-: (let ((thyme (float-time))) (scan-lists 947171 -1 1) (- (float-time) thyme)) , I get 0.013844966888427734 seconds, 2% of the above figure. It is true that in CC-Mode, that bit of the code is deeply nested inside some macros which manipulate text properties. But when I include these in the manual call of scan-lists, they barely make any difference. How can this one single scan-lists called from CC Mode be so slow, yet the identical call from the minibuffer be 50 times as fast? My understanding is that scan-lists is a primitive operation, unaffected by virtually any context (apart from specific things like parse-sexp-ignore-comments and syntax-table text properties which are meant to affect it). I'm at a loss for ideas right now. Suggestions would be most welcome. -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-06-25 21:32 ` Alan Mackenzie @ 2014-06-26 2:51 ` Stefan Monnier 2014-06-27 20:34 ` Alan Mackenzie 0 siblings, 1 reply; 93+ messages in thread From: Stefan Monnier @ 2014-06-26 2:51 UTC (permalink / raw) To: Alan Mackenzie; +Cc: 16526-done > How can this one single scan-lists called from CC Mode be so slow, yet > the identical call from the minibuffer be 50 times as fast? Do the two return the same position? The time taken by scan-lists is proportional to the "distance", so a 50x slowdown would not be surprising if it goes 50x further. > My understanding is that scan-lists is a primitive operation, > unaffected by virtually any context (apart from specific things like > parse-sexp-ignore-comments and syntax-table text properties which are > meant to affect it). Another influence could be parse-sexp-lookup-properties, tho it definitely shouldn't account for more than a few percents. Stefan ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-06-26 2:51 ` Stefan Monnier @ 2014-06-27 20:34 ` Alan Mackenzie 2014-06-27 22:33 ` Stefan Monnier 0 siblings, 1 reply; 93+ messages in thread From: Alan Mackenzie @ 2014-06-27 20:34 UTC (permalink / raw) To: Stefan Monnier; +Cc: 16526-done Hi, Stefan. Thanks for the reply. On Wed, Jun 25, 2014 at 10:51:24PM -0400, Stefan Monnier wrote: > > How can this one single scan-lists called from CC Mode be so slow, yet > > the identical call from the minibuffer be 50 times as fast? > Do the two return the same position? They do, yes. > The time taken by scan-lists is proportional to the "distance", so a > 50x slowdown would not be surprising if it goes 50x further. This is surely not the problem. 50x further would have taken point well outside the bounds of the file to a negative offset. Besides, I printed out the end position (in both cases) with `message'. That position was of the opening brace of syms_of_xdisp. > > My understanding is that scan-lists is a primitive operation, > > unaffected by virtually any context (apart from specific things like > > parse-sexp-ignore-comments and syntax-table text properties which are > > meant to affect it). > Another influence could be parse-sexp-lookup-properties, tho it > definitely shouldn't account for more than a few percents. parse-sexp-lookup-properties was set in both cases. (CC Mode sets it buffer locally in its initialisation.) Could CC Mode's use of category text properties be causing this delay, somehow? Could scan-lists be exhausting some sort of resource in this particular invocation which needs ~0.7s to replenish? Or something like that? > Stefan -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-06-27 20:34 ` Alan Mackenzie @ 2014-06-27 22:33 ` Stefan Monnier 2014-06-27 22:54 ` Stefan Monnier [not found] ` <jwv8uoim0bm.fsf-monnier+emacsbugs@gnu.org> 0 siblings, 2 replies; 93+ messages in thread From: Stefan Monnier @ 2014-06-27 22:33 UTC (permalink / raw) To: Alan Mackenzie; +Cc: 16526-done > Could CC Mode's use of category text properties be causing this delay, > somehow? I can't see how/why. > Could scan-lists be exhausting some sort of resource in this particular > invocation which needs ~0.7s to replenish? Or something like that? Or a GC call or something like that? Can't think of any reason why that could happen, no. `profiler-start' is not very fine-grained, so it probably won't give you much insight as to what's going on inside `scan-lists', but at least it should be easy to try. Stefan ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-06-27 22:33 ` Stefan Monnier @ 2014-06-27 22:54 ` Stefan Monnier [not found] ` <jwv8uoim0bm.fsf-monnier+emacsbugs@gnu.org> 1 sibling, 0 replies; 93+ messages in thread From: Stefan Monnier @ 2014-06-27 22:54 UTC (permalink / raw) To: Alan Mackenzie; +Cc: 16526-done >> Could scan-lists be exhausting some sort of resource in this particular >> invocation which needs ~0.7s to replenish? Or something like that? > Or a GC call or something like that? Can't think of any reason why that > could happen, no. One way to figure it out is to change your code such that scan-lists is always called twice in a row. If the time spend is the same both time, then it's definitely not some sort of resources exhaustion that just happens to slow down this one particular call. Stefan ^ permalink raw reply [flat|nested] 93+ messages in thread
[parent not found: <jwv8uoim0bm.fsf-monnier+emacsbugs@gnu.org>]
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression [not found] ` <jwv8uoim0bm.fsf-monnier+emacsbugs@gnu.org> @ 2014-06-28 13:00 ` Alan Mackenzie 2014-06-28 14:00 ` martin rudalics ` (3 more replies) 0 siblings, 4 replies; 93+ messages in thread From: Alan Mackenzie @ 2014-06-28 13:00 UTC (permalink / raw) To: Stefan Monnier; +Cc: 16526-done Hi, Stefan. On Fri, Jun 27, 2014 at 06:54:55PM -0400, Stefan Monnier wrote: > >> Could scan-lists be exhausting some sort of resource in this particular > >> invocation which needs ~0.7s to replenish? Or something like that? > > Or a GC call or something like that? Can't think of any reason why that > > could happen, no. > One way to figure it out is to change your code such that scan-lists is > always called twice in a row. If the time spend is the same both time, > then it's definitely not some sort of resources exhaustion that just > happens to slow down this one particular call. Yes, the second call takes as long as the first call. One thing that did make a big difference was binding parse-sexp-ignore-comments to nil around a call to scan-lists. My two calls to (scan-lists 947171 -1 1) give these results: parse-sexp-ignore-comments | end position time --------------------------------------------------------------------- t | 919215 0.6976802349090576 nil | 899080 0.0021085739135742188 So, although with parse-..-comments nil, the distance traversed was greater, the time taken was a factor ~300 less. This suggests that comments have something to do with the problem. parse_sexp_ignore_comments is only tested twice in scan_lists. The first time, it is only setting up syntax table variables and suchlike after having half-detected a comment closer. The second time, back_comment gets called. It seems likely the problem is in back_comment. AH!!!!! GOT IT!!!! What causes the slowdown is binding open-paren-in-column-0-is-defun-start to nil around the scan-lists. In CC Mode's "engine" parts, that variable is bound to nil. There are good reasons for this (which I can't precisely recall just at the moment). In CC Mode, "'" has string syntax. So any C comment with an odd number of apostrophes looks, to back_comment, like it has an "unbalanced string", and the code ends up at label lossage: in back_comment. Here find_defun_start is called, and this returns BOB when open-paren-..-0 is nil. From here (BOB) the code scans forward to check this putative "unbalanced string". It's a long way from BOB to ~900k, hence the sluggishness. Where do we go from here? > Stefan -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-06-28 13:00 ` Alan Mackenzie @ 2014-06-28 14:00 ` martin rudalics 2014-06-28 14:34 ` Stefan Monnier ` (2 subsequent siblings) 3 siblings, 0 replies; 93+ messages in thread From: martin rudalics @ 2014-06-28 14:00 UTC (permalink / raw) To: Alan Mackenzie, Stefan Monnier; +Cc: 16526-done > AH!!!!! GOT IT!!!! What causes the slowdown is binding > open-paren-in-column-0-is-defun-start to nil around the scan-lists. In > CC Mode's "engine" parts, that variable is bound to nil. There are good > reasons for this (which I can't precisely recall just at the moment). > > In CC Mode, "'" has string syntax. So any C comment with an odd number > of apostrophes looks, to back_comment, like it has an "unbalanced string", > and the code ends up at label lossage: in back_comment. Here > find_defun_start is called, and this returns BOB when open-paren-..-0 is > nil. From here (BOB) the code scans forward to check this putative > "unbalanced string". It's a long way from BOB to ~900k, hence the > sluggishness. > > Where do we go from here? In every version of Emacs I'm actually doing some work I have disabled CC mode's `open-paren-in-column-0-is-defun-start' bindings. Otherwise, working on a file like xdisp.c would be virtually impossible for me. As for the release I would simply do what I proposed earlier - make these overriding bindings customizable. So someone who wants to comment out code with a paren in the first column can have the "correct" behavior while people like me can continue work with "incorrect" but yet tame behavior. And obviously I could continue to work without having bzr status tell me that I've changed CC mode files ;-) martin ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-06-28 13:00 ` Alan Mackenzie 2014-06-28 14:00 ` martin rudalics @ 2014-06-28 14:34 ` Stefan Monnier [not found] ` <53AECA88.7010401@gmx.at> [not found] ` <jwvsimpksv1.fsf-monnier+emacsbugs@gnu.org> 3 siblings, 0 replies; 93+ messages in thread From: Stefan Monnier @ 2014-06-28 14:34 UTC (permalink / raw) To: Alan Mackenzie; +Cc: 16526-done > Where do we go from here? Not sure. Would `syntax-ppss' return correct values from the code in question? If yes, then changing back_comment to call back to Elisp and use syntax-ppss in the lossage case should eliminate this algorithmic problem. Stefan ^ permalink raw reply [flat|nested] 93+ messages in thread
[parent not found: <53AECA88.7010401@gmx.at>]
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression [not found] ` <53AECA88.7010401@gmx.at> @ 2014-06-28 14:55 ` Alan Mackenzie 2014-06-28 15:12 ` Eli Zaretskii 2014-06-29 8:44 ` martin rudalics 0 siblings, 2 replies; 93+ messages in thread From: Alan Mackenzie @ 2014-06-28 14:55 UTC (permalink / raw) To: martin rudalics; +Cc: 16526-done Hi, Martin. On Sat, Jun 28, 2014 at 04:00:40PM +0200, martin rudalics wrote: > > AH!!!!! GOT IT!!!! What causes the slowdown is binding > > open-paren-in-column-0-is-defun-start to nil around the scan-lists. In > > CC Mode's "engine" parts, that variable is bound to nil. There are good > > reasons for this (which I can't precisely recall just at the moment). > > In CC Mode, "'" has string syntax. So any C comment with an odd number > > of apostrophes looks, to back_comment, like it has an "unbalanced string", > > and the code ends up at label lossage: in back_comment. Here > > find_defun_start is called, and this returns BOB when open-paren-..-0 is > > nil. From here (BOB) the code scans forward to check this putative > > "unbalanced string". It's a long way from BOB to ~900k, hence the > > sluggishness. > > Where do we go from here? > In every version of Emacs I'm actually doing some work I have disabled > CC mode's `open-paren-in-column-0-is-defun-start' bindings. This is harmless (and thus helpful) in code conforming to GNU standards. As you note below, it causes confusion and heartache in other circumstances. > Otherwise, working on a file like xdisp.c would be virtually impossible > for me. As for the release I would simply do what I proposed earlier - > make these overriding bindings customizable. I'd far rather the code worked properly (including fast enough). Making a choice between two ugly workarounds customisable would be short-changing users. > So someone who wants to comment out code with a paren in the first > column can have the "correct" behavior while people like me can > continue work with "incorrect" but yet tame behavior. And obviously I > could continue to work without having bzr status tell me that I've > changed CC mode files ;-) This particular scan-lists which took 0.7s had to traverse 65 comments, of which 29 had an odd number of apostrophes. Scanning xdisp.c from BOB to syms_of_xdisp on my machine takes 0.024s. 28 * 0.024s = 0.67s. So if there were simple cacheing in syntax.c, such that the scan from BOB was done at most once for each scan-lists, the sluggishness would largely vanish in this case. If you look at find_defun_start in syntax.c, you'll be struck by just what an ugly kludge the code for null open_paren_.._start is. Substantial improvement must surely be possible. > martin -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-06-28 14:55 ` Alan Mackenzie @ 2014-06-28 15:12 ` Eli Zaretskii 2014-06-28 16:30 ` Alan Mackenzie 2014-06-29 8:44 ` martin rudalics 1 sibling, 1 reply; 93+ messages in thread From: Eli Zaretskii @ 2014-06-28 15:12 UTC (permalink / raw) To: Alan Mackenzie; +Cc: 16526 > Date: Sat, 28 Jun 2014 14:55:09 +0000 > From: Alan Mackenzie <acm@muc.de> > Cc: 16526-done@debbugs.gnu.org > > This particular scan-lists which took 0.7s had to traverse 65 comments, > of which 29 had an odd number of apostrophes. Scanning xdisp.c from BOB > to syms_of_xdisp on my machine takes 0.024s. 28 * 0.024s = 0.67s. So if > there were simple cacheing in syntax.c, such that the scan from BOB was > done at most once for each scan-lists, the sluggishness would largely > vanish in this case. Sorry for asking the obvious: why cannot the code know that an apostrophe inside a comment is just a simple character of no special significance? Why does it need to treat apostrophes _inside_comments_ specially? ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-06-28 15:12 ` Eli Zaretskii @ 2014-06-28 16:30 ` Alan Mackenzie 0 siblings, 0 replies; 93+ messages in thread From: Alan Mackenzie @ 2014-06-28 16:30 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 16526 Hi, Eli. On Sat, Jun 28, 2014 at 06:12:53PM +0300, Eli Zaretskii wrote: > > Date: Sat, 28 Jun 2014 14:55:09 +0000 > > From: Alan Mackenzie <acm@muc.de> > > Cc: 16526-done@debbugs.gnu.org > > This particular scan-lists which took 0.7s had to traverse 65 comments, > > of which 29 had an odd number of apostrophes. Scanning xdisp.c from BOB > > to syms_of_xdisp on my machine takes 0.024s. 28 * 0.024s = 0.67s. So if > > there were simple cacheing in syntax.c, such that the scan from BOB was > > done at most once for each scan-lists, the sluggishness would largely > > vanish in this case. > Sorry for asking the obvious: why cannot the code know that an > apostrophe inside a comment is just a simple character of no special > significance? Why does it need to treat apostrophes _inside_comments_ > specially? I think it's because whilst scanning backwards, it's not known that the comment ender actually ends a comment. For example: /* */ " /* " */ ^ | . Here we actually have a comment followed by a string followed by an unmated comment closer. If, at the marked position, we were to assume that the " was "nothing special", we'd mis-parse the above as a comment containing a quote mark, then get horribly confused trying to find the mating double quote mark for the first ". Or something like that. -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-06-28 14:55 ` Alan Mackenzie 2014-06-28 15:12 ` Eli Zaretskii @ 2014-06-29 8:44 ` martin rudalics 2014-06-29 9:17 ` Alan Mackenzie 1 sibling, 1 reply; 93+ messages in thread From: martin rudalics @ 2014-06-29 8:44 UTC (permalink / raw) To: Alan Mackenzie; +Cc: 16526-done > Making a choice between two ugly workarounds customisable would be > short-changing users. My `open-paren-in-column-0-is-defun-start' is t and by ignoring that setting in CC mode you are already short-changing me. martin ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-06-29 8:44 ` martin rudalics @ 2014-06-29 9:17 ` Alan Mackenzie 2014-06-29 10:06 ` martin rudalics [not found] ` <53AFE536.7010407@gmx.at> 0 siblings, 2 replies; 93+ messages in thread From: Alan Mackenzie @ 2014-06-29 9:17 UTC (permalink / raw) To: martin rudalics; +Cc: 16526-done Hi, Martin. On Sun, Jun 29, 2014 at 10:44:42AM +0200, martin rudalics wrote: > > Making a choice between two ugly workarounds customisable would be > > short-changing users. > My `open-paren-in-column-0-is-defun-start' is t and by ignoring that > setting in CC mode you are already short-changing me. That's a bit philosophical. open-..-start is advertised as a high level option, and CC Mode only binds it to nil at a low level, the "engine" level. Binding user options to set values at a low level is quite a common practice in Elisp programming. The actual bug here is that find_defun_start in syntax.c doesn't do any cacheing, hence is scanning from BOB far too often. How about we see how things work once this is fixed. > martin -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-06-29 9:17 ` Alan Mackenzie @ 2014-06-29 10:06 ` martin rudalics [not found] ` <53AFE536.7010407@gmx.at> 1 sibling, 0 replies; 93+ messages in thread From: martin rudalics @ 2014-06-29 10:06 UTC (permalink / raw) To: Alan Mackenzie; +Cc: 16526-done > That's a bit philosophical. open-..-start is advertised as a high level > option, and CC Mode only binds it to nil at a low level, the "engine" > level. Binding user options to set values at a low level is quite a > common practice in Elisp programming. It is a quite bad common practice in Elisp programming. > The actual bug here is that find_defun_start in syntax.c doesn't do any > cacheing, hence is scanning from BOB far too often. How about we see > how things work once this is fixed. We're discussing this problem for some ten years now and I'm afraid we won't find a solution for the imminent release. martin ^ permalink raw reply [flat|nested] 93+ messages in thread
[parent not found: <53AFE536.7010407@gmx.at>]
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression [not found] ` <53AFE536.7010407@gmx.at> @ 2014-06-29 12:48 ` Alan Mackenzie 2014-06-29 14:18 ` martin rudalics 0 siblings, 1 reply; 93+ messages in thread From: Alan Mackenzie @ 2014-06-29 12:48 UTC (permalink / raw) To: martin rudalics; +Cc: 16526-done Hi, Martin. On Sun, Jun 29, 2014 at 12:06:46PM +0200, martin rudalics wrote: > > That's a bit philosophical. open-..-start is advertised as a high level > > option, and CC Mode only binds it to nil at a low level, the "engine" > > level. Binding user options to set values at a low level is quite a > > common practice in Elisp programming. > It is a quite bad common practice in Elisp programming. :-) We're down at the philosophy level again. > > The actual bug here is that find_defun_start in syntax.c doesn't do any > > cacheing, hence is scanning from BOB far too often. How about we see > > how things work once this is fixed. > We're discussing this problem for some ten years now and I'm afraid we > won't find a solution for the imminent release. We've been discussing it for some while, yes, but a concrete diagnosis of the problem first happened yesterday, as far as I'm aware. Do you feel like fixing it? I think you know the C code better than I do, and you're highly motivated. Once fixed, Stefan might be inclined to include the fix in 24.4. As I suggested yesterday, what is needed is for find_defun_start to actually determine the beginning-of-defun before POS/POS_BYTE (using scan_sexps_forward) rather than just giving up and returning BOB. This position must then be cached for future find_defun_start calls. The cacheing mechanism is already in place for non-nil open-...-start. The above simple cacheing might not be adequate in theory, but I'm guessing that in practice it will be a substantial win. > martin -- Alan Mackenzie (Nuremberg, Germany) ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-06-29 12:48 ` Alan Mackenzie @ 2014-06-29 14:18 ` martin rudalics 2014-06-29 14:41 ` Alan Mackenzie [not found] ` <20140629144151.GD2948@acm.acm> 0 siblings, 2 replies; 93+ messages in thread From: martin rudalics @ 2014-06-29 14:18 UTC (permalink / raw) To: Alan Mackenzie; +Cc: 16526-done > As I suggested yesterday, what is needed is for find_defun_start to > actually determine the beginning-of-defun before POS/POS_BYTE (using > scan_sexps_forward) rather than just giving up and returning BOB. > This position must then be cached for future find_defun_start calls. > The cacheing mechanism is already in place for non-nil open-...-start. I don't even understand why you can't use the 9th element returned by `syntax-ppss' to get the beginning of the outermost defun enclosing `point'. martin ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-06-29 14:18 ` martin rudalics @ 2014-06-29 14:41 ` Alan Mackenzie [not found] ` <20140629144151.GD2948@acm.acm> 1 sibling, 0 replies; 93+ messages in thread From: Alan Mackenzie @ 2014-06-29 14:41 UTC (permalink / raw) To: martin rudalics; +Cc: 16526-done On Sun, Jun 29, 2014 at 04:18:42PM +0200, martin rudalics wrote: > > As I suggested yesterday, what is needed is for find_defun_start to > > actually determine the beginning-of-defun before POS/POS_BYTE (using > > scan_sexps_forward) rather than just giving up and returning BOB. > > This position must then be cached for future find_defun_start calls. > > The cacheing mechanism is already in place for non-nil open-...-start. > I don't even understand why you can't use the 9th element returned by > `syntax-ppss' to get the beginning of the outermost defun enclosing > `point'. scan-lists, a primitive, must be utterly robust. syntax-ppss is too fragile to be used here without a lot of hardening. syntax-ppss's cache is rendered invalid at any operation which changes the syntax table (e.g. `modify-syntax-entry'), or changes to a different syntax table (e.g. `with-syntax-table'), or when a syntax-table text property/overlay is applied to the buffer, or even when a symbol's property list is changed when that symbol is the value of a category text property. CC Mode does all these things, and does all of them apart from the first during run time, not merely at mode initialisation. Also, the syntax-ppss cache's functioning is dependent upon before-change-functions, which can be bound to nil by any program at any time. If one were to harden syntax-ppss against all these things, one would probably end up calculating the cache from scratch every time, in effect. scan-lists is a primitive, and must function correctly regardless of any trickery which might be played on it. > martin -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 93+ messages in thread
[parent not found: <20140629144151.GD2948@acm.acm>]
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression [not found] ` <20140629144151.GD2948@acm.acm> @ 2014-06-29 16:01 ` martin rudalics [not found] ` <53B03876.9070307@gmx.at> ` (2 subsequent siblings) 3 siblings, 0 replies; 93+ messages in thread From: martin rudalics @ 2014-06-29 16:01 UTC (permalink / raw) To: Alan Mackenzie; +Cc: 16526-done > scan-lists, a primitive, must be utterly robust. syntax-ppss is too > fragile to be used here without a lot of hardening. > > syntax-ppss's cache is rendered invalid at any operation which changes > the syntax table (e.g. `modify-syntax-entry'), or changes to a different > syntax table (e.g. `with-syntax-table'), or when a syntax-table text > property/overlay is applied to the buffer, or even when a symbol's > property list is changed when that symbol is the value of a category > text property. CC Mode does all these things, and does all of them > apart from the first during run time, not merely at mode initialisation. How can any of these affect the cached start position of a defun before the position where the buffer contents were changed? > Also, the syntax-ppss cache's functioning is dependent upon > before-change-functions, which can be bound to nil by any program at any > time. There's an appropriate advice what to do in such case. > If one were to harden syntax-ppss against all these things, one would > probably end up calculating the cache from scratch every time, in > effect. Can you give an example? > scan-lists is a primitive, and must function correctly regardless of any > trickery which might be played on it. You can easily play trickery on `scan-lists' if you start it within a comment or string. So `syntax-ppss' is at least as primitive as `scan-lists' (especially when the latter is used with negative COUNT). Anyway, IIUC this implies that CC mode can't work with `syntax-ppss' at all. If that is true, then `open-paren-in-column-0-is-defun-start' was indeed the last resort that made editing larger files possible. martin ^ permalink raw reply [flat|nested] 93+ messages in thread
[parent not found: <53B03876.9070307@gmx.at>]
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression [not found] ` <53B03876.9070307@gmx.at> @ 2014-06-29 17:49 ` Alan Mackenzie 2014-06-30 7:55 ` martin rudalics ` (2 more replies) 0 siblings, 3 replies; 93+ messages in thread From: Alan Mackenzie @ 2014-06-29 17:49 UTC (permalink / raw) To: martin rudalics; +Cc: 16526-done Hi, Martin. On Sun, Jun 29, 2014 at 06:01:58PM +0200, martin rudalics wrote: > > scan-lists, a primitive, must be utterly robust. syntax-ppss is too > > fragile to be used here without a lot of hardening. > > syntax-ppss's cache is rendered invalid at any operation which changes > > the syntax table (e.g. `modify-syntax-entry'), or changes to a different > > syntax table (e.g. `with-syntax-table'), or when a syntax-table text > > property/overlay is applied to the buffer, or even when a symbol's > > property list is changed when that symbol is the value of a category > > text property. CC Mode does all these things, and does all of them > > apart from the first during run time, not merely at mode initialisation. > How can any of these affect the cached start position of a defun before > the position where the buffer contents were changed? In this context, the "start of defun" means an outermost paren of some sort, nothing more, nothing less. Any of the changes above could disturb this: For example, adding an open-paren syntax-table property to a character which thereby becomes the BOD. Or temporarily switching to the Pascal syntax table, where "{" and "}" are comment brackets. I'm not saying that something like this will happen on a regular basis, but it's definitely possible. > > Also, the syntax-ppss cache's functioning is dependent upon > > before-change-functions, which can be bound to nil by any program at any > > time. > There's an appropriate advice what to do in such case. Primitive functions are deaf to advice. You're surely not suggesting that a primitive like scan-lists should become vulnerable to high-level programmers failing to follow advice? If this were to be done, scan-lists would only work most of the time, not all of the time. This would be catastrophic for Emacs. > > If one were to harden syntax-ppss against all these things, one would > > probably end up calculating the cache from scratch every time, in > > effect. > Can you give an example? An example of what? What I meant was, each time you used syntax-ppss from scan-lists, you'd somehow need to be sure that a syntax-table entry hadn't been changed, etc. I can't really see how this would be possible. You'd somehow need to handle constructs like (with-syntax-table c++-template-syntax-table .... (scan-lists (point) -1 1) ....) . > > scan-lists is a primitive, and must function correctly regardless of any > > trickery which might be played on it. > You can easily play trickery on `scan-lists' if you start it within a > comment or string. No. scan-lists works according to its spec even if you start it inside a comment/string. It's effect is well defined. For example if you write parens inside a comment, C-M-n and friends do the right thing there. > So `syntax-ppss' is at least as primitive as `scan-lists' (especially > when the latter is used with negative COUNT). Sorry, but that's utter rubbish. syntax-ppss is a high-level convenience function, which if used carefully by the lisp programmer gives correct results. By contrast, scan-lists does precisely what it says, no ifs and no buts. Even with a negative COUNT. > Anyway, IIUC this implies that CC mode can't work with `syntax-ppss' at > all. If that is true, then `open-paren-in-column-0-is-defun-start' was > indeed the last resort that made editing larger files possible. CC Mode doesn't use syntax-ppss, but I can't see how that's implied by anything we've been discussing so far. It does maintain its own caches which fulfil the same purpose. For example, there's a syntactic cache which treats preprocessor constructs as comments, something syntax-ppss can't do. open-..-start being t is a kludge which works for certain types of files and situations and not others. It was causing hard to fathom errors in CC Mode, particularly C and C++. Do I take it you're not keen on enhancing find_defun_start in the manner I suggested? > martin -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-06-29 17:49 ` Alan Mackenzie @ 2014-06-30 7:55 ` martin rudalics 2014-06-30 13:48 ` Stefan Monnier [not found] ` <53B117D6.1050306@gmx.at> 2 siblings, 0 replies; 93+ messages in thread From: martin rudalics @ 2014-06-30 7:55 UTC (permalink / raw) To: Alan Mackenzie; +Cc: 16526-done >> How can any of these affect the cached start position of a defun before >> the position where the buffer contents were changed? > > In this context, the "start of defun" means an outermost paren of some > sort, nothing more, nothing less. Any of the changes above could disturb > this: For example, adding an open-paren syntax-table property to a > character which thereby becomes the BOD. Or temporarily switching to the > Pascal syntax table, where "{" and "}" are comment brackets. I'm not > saying that something like this will happen on a regular basis, but it's > definitely possible. Then you can forget caching. >> > Also, the syntax-ppss cache's functioning is dependent upon >> > before-change-functions, which can be bound to nil by any program at any >> > time. > >> There's an appropriate advice what to do in such case. > > Primitive functions are deaf to advice. You're surely not suggesting > that a primitive like scan-lists should become vulnerable to high-level > programmers failing to follow advice? If this were to be done, > scan-lists would only work most of the time, not all of the time. This > would be catastrophic for Emacs. I meant that if someone is going to disable `before-change-functions' that someone has to take care of flushing the cache. > An example of what? What I meant was, each time you used syntax-ppss > from scan-lists, you'd somehow need to be sure that a syntax-table entry > hadn't been changed, etc. I can't really see how this would be possible. > You'd somehow need to handle constructs like > > (with-syntax-table c++-template-syntax-table > .... > (scan-lists (point) -1 1) > ....) > > . And how would a defun start cache handle such constructs? > No. scan-lists works according to its spec even if you start it inside a > comment/string. It's effect is well defined. For example if you writen > parens inside a comment, C-M-n and friends do the right thing there. Here C-M-n is bound to `forward-list' which according to its doc-string "assumes point is not in a string or comment". `scan-lists' has precisely the same problems as `syntax-ppss' wrt syntax changes. >> So `syntax-ppss' is at least as primitive as `scan-lists' (especially >> when the latter is used with negative COUNT). > > Sorry, but that's utter rubbish. syntax-ppss is a high-level convenience > function, which if used carefully by the lisp programmer gives correct > results. We're not talking about `scan-lists' alone. We're talking about `scan-lists' (or more precisely find_defun_start) with a cache of previously calculated positions. > By contrast, scan-lists does precisely what it says, no ifs and no buts. > Even with a negative COUNT. Any "problems" of `syntax-ppss' in this regard are the problems of scan_lists plus those of maintaining a cache. No ifs and no buts. >> Anyway, IIUC this implies that CC mode can't work with `syntax-ppss' at >> all. If that is true, then `open-paren-in-column-0-is-defun-start' was >> indeed the last resort that made editing larger files possible. > > CC Mode doesn't use syntax-ppss, but I can't see how that's implied by > anything we've been discussing so far. It does maintain its own caches > which fulfil the same purpose. For example, there's a syntactic cache > which treats preprocessor constructs as comments, something syntax-ppss > can't do. And how do you invalidate that cache? > open-..-start being t is a kludge which works for certain types of files > and situations and not others. It was causing hard to fathom errors in > CC Mode, particularly C and C++. I can live with such errors. I can't live with the slowdown. > Do I take it you're not keen on enhancing find_defun_start in the manner > I suggested? What you're asking for is impossible: (1) You want to base find_defun_start on scan_lists starting at BOB. This means that you need a function that repeatedly calls scan_lists, stopping whenever depth reaches zero and remembers that position, returning the last such position before FROM. Such a function exists already - it's called `parse-partial-sexp'. (2) You want to avoid that function call scan_lists repeatedly by caching previously found positions. Such a function exists already - it's called `syntax-ppss'. (3) You want that function to work even if someone changes the syntax table or disables `before-change-functions' without flushing its cache. Such a function does not exist and never will. martin ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-06-29 17:49 ` Alan Mackenzie 2014-06-30 7:55 ` martin rudalics @ 2014-06-30 13:48 ` Stefan Monnier [not found] ` <53B117D6.1050306@gmx.at> 2 siblings, 0 replies; 93+ messages in thread From: Stefan Monnier @ 2014-06-30 13:48 UTC (permalink / raw) To: Alan Mackenzie; +Cc: 16526-done > For example, there's a syntactic cache which treats preprocessor > constructs as comments, something syntax-ppss can't do. Can you expand on why you think syntax-ppss can't do that? Stefan ^ permalink raw reply [flat|nested] 93+ messages in thread
[parent not found: <53B117D6.1050306@gmx.at>]
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression [not found] ` <53B117D6.1050306@gmx.at> @ 2014-07-02 20:05 ` Alan Mackenzie [not found] ` <20140702200522.GB3823@acm.acm> 1 sibling, 0 replies; 93+ messages in thread From: Alan Mackenzie @ 2014-07-02 20:05 UTC (permalink / raw) To: martin rudalics; +Cc: 16526-done Hi, Martin. On Mon, Jun 30, 2014 at 09:55:02AM +0200, martin rudalics wrote: > >> How can any of these affect the cached start position of a defun before > >> the position where the buffer contents were changed? > > In this context, the "start of defun" means an outermost paren of some > > sort, nothing more, nothing less. Any of the changes above could disturb > > this: For example, adding an open-paren syntax-table property to a > > character which thereby becomes the BOD. Or temporarily switching to the > > Pascal syntax table, where "{" and "}" are comment brackets. I'm not > > saying that something like this will happen on a regular basis, but it's > > definitely possible. > Then you can forget caching. No. The particular rogue invocation of scan-lists which caused this (sub-)thread scans from BOB to near EOB 29 times. Inside scan-lists, _NO_ changes to syntax-tables, s-t text properties etc. are possible. What I'm suggesting is that cacheing that first scan from BOB will be a big win for many time-consuming scan-listses. [ .... ] > I meant that if someone is going to disable `before-change-functions' > that someone has to take care of flushing the cache. OK. > > An example of what? What I meant was, each time you used syntax-ppss > > from scan-lists, you'd somehow need to be sure that a syntax-table entry > > hadn't been changed, etc. I can't really see how this would be possible. > > You'd somehow need to handle constructs like > > (with-syntax-table c++-template-syntax-table > > .... > > (scan-lists (point) -1 1) > > ....) > > . > And how would a defun start cache handle such constructs? Such a cache would be initialised to nil within a particular invocation of scan-lists, hence nothing like the above could cause any trouble. > > No. scan-lists works according to its spec even if you start it inside a > > comment/string. It's effect is well defined. For example if you writen > > parens inside a comment, C-M-n and friends do the right thing there. > Here C-M-n is bound to `forward-list' which according to its doc-string > "assumes point is not in a string or comment". `scan-lists' has > precisely the same problems as `syntax-ppss' wrt syntax changes. scan-lists is an atomic function, without memory of any state. It's functionality is wholly determined by the current buffer state and the current setting of (quite a few) state variables. syntax-ppss is motivated by cacheing historical state, hence is critically different. > >> So `syntax-ppss' is at least as primitive as `scan-lists' (especially > >> when the latter is used with negative COUNT). > > Sorry, but that's utter rubbish. syntax-ppss is a high-level convenience > > function, which if used carefully by the lisp programmer gives correct > > results. > We're not talking about `scan-lists' alone. We're talking about > `scan-lists' (or more precisely find_defun_start) with a cache of > previously calculated positions. OK, I think I see what you're getting at. You're thinking of a cache which would endure over random buffer changes. The cache I was intending would be flushed at the beginning of each scan-lists. "What I tell you three times is true." (Lewis Carroll, The Hunting of the Snark). > > By contrast, scan-lists does precisely what it says, no ifs and no buts. > > Even with a negative COUNT. > Any "problems" of `syntax-ppss' in this regard are the problems of > scan_lists plus those of maintaining a cache. No ifs and no buts. > >> Anyway, IIUC this implies that CC mode can't work with `syntax-ppss' at > >> all. If that is true, then `open-paren-in-column-0-is-defun-start' was > >> indeed the last resort that made editing larger files possible. > > CC Mode doesn't use syntax-ppss, but I can't see how that's implied by > > anything we've been discussing so far. It does maintain its own caches > > which fulfil the same purpose. For example, there's a syntactic cache > > which treats preprocessor constructs as comments, something syntax-ppss > > can't do. > And how do you invalidate that cache? It's truncated at buffer changes. It doesn't contain any information which could become stale on any of the other sorts of modifications we've been talking about, or it isn't used when they could hurt anything. That this cache has a tightly defined purpose is why it can be robust, whereas syntax-ppss's cache, being very general purpose, is vulnerable to certain changes. > > open-..-start being t is a kludge which works for certain types of files > > and situations and not others. It was causing hard to fathom errors in > > CC Mode, particularly C and C++. > I can live with such errors. I can't live with the slowdown. I'm hoping the slowdown will go away, or at least become tolerable, when scan-lists is optimised. > > Do I take it you're not keen on enhancing find_defun_start in the manner > > I suggested? > What you're asking for is impossible: > (1) You want to base find_defun_start on scan_lists starting at BOB. No, on scan_sexps_forward, which (despite the confusing name) is the core of parse-partial-sexp without its lispy arguments. > This means that you need a function that repeatedly calls > scan_lists, stopping whenever depth reaches zero and remembers that > position, returning the last such position before FROM. Such a > function exists already - it's called `parse-partial-sexp'. Yes. Or scan_sexps_forward which is the C core of it. > (2) You want to avoid that function call scan_lists repeatedly by > caching previously found positions. Such a function exists already > - it's called `syntax-ppss'. I'd have nothing against using syntax-ppss, as long as its cache was bound to nil for each scan-lists call - except it would cause some slowdown (compared with a special-purpose cache written in C), since it goes through the lisp bytecode interpreter. > (3) You want that function to work even if someone changes the syntax > table or disables `before-change-functions' without flushing its > cache. Such a function does not exist and never will. No, I want that cache to be flushed for each scan-lists call, so that the first scan of (nearly) the whole buffer will create the cache, and the other 28 scans will use that cache. > martin -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 93+ messages in thread
[parent not found: <20140702200522.GB3823@acm.acm>]
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression [not found] ` <20140702200522.GB3823@acm.acm> @ 2014-07-03 1:57 ` Stefan Monnier 2014-07-03 8:40 ` martin rudalics [not found] ` <jwv61jf2owy.fsf-monnier+emacsbugs@gnu.org> 2 siblings, 0 replies; 93+ messages in thread From: Stefan Monnier @ 2014-07-03 1:57 UTC (permalink / raw) To: Alan Mackenzie; +Cc: 16526-done > No. The particular rogue invocation of scan-lists which caused this > (sub-)thread scans from BOB to near EOB 29 times. Inside scan-lists, > _NO_ changes to syntax-tables, s-t text properties etc. are possible. > What I'm suggesting is that cacheing that first scan from BOB will be a > big win for many time-consuming scan-listses. Here's the situation: we can add some special code to handle your case. But adding code which will use syntax-ppss would be more beneficial for 99% of the major modes. Adding a cache that only works within a single scan-lists instance is too much trouble for too little gain. Adding a cache that is flushed less often means either it will suffer from the same limitations as syntax-ppss (so we may as well use syntax-ppss), or it needs to additionally hook into the text-property and set-syntax-table code to be flushed in those extra corner cases, and there again these extra checks will be only useful for those rare modes like CC-mode and will be at best harmless and in some cases detrimental to performance compared to simply using syntax-ppss. IOW, using syntax-ppss for find_defun_start is The Right Thing to do. And CC-mode should then be fixed to take advantage of it. Stefan ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression [not found] ` <20140702200522.GB3823@acm.acm> 2014-07-03 1:57 ` Stefan Monnier @ 2014-07-03 8:40 ` martin rudalics [not found] ` <jwv61jf2owy.fsf-monnier+emacsbugs@gnu.org> 2 siblings, 0 replies; 93+ messages in thread From: martin rudalics @ 2014-07-03 8:40 UTC (permalink / raw) To: Alan Mackenzie; +Cc: 16526-done > No. The particular rogue invocation of scan-lists which caused this > (sub-)thread scans from BOB to near EOB 29 times. Inside scan-lists, > _NO_ changes to syntax-tables, s-t text properties etc. are possible. > What I'm suggesting is that cacheing that first scan from BOB will be a > big win for many time-consuming scan-listses. To obtain a meaningful result from `scan-lists' with a negative COUNT, we have to know whether the starting point is outside a comment or string. This means that we either first have to scan from BOB till that point or have the results from a previous scan in a not yet invalidated cache anyway. Can we agree on that? Now it's possible that CC-mode for some magic reason knows that the starting point meets the requirement above. In that case the magic used should also assure that `scan-lists' stops at a reasonable position (one known to have DEPTH zero when scanned from BOB) by narrowing the buffer appropriately. Otherwise we need some heuristics to provide a reasonable amount of defun starters to be eventually used by back_comment (I suppose it's that routine causing our problems). In any case, these starters must be provided by `parse-partial-sexp' (or forward_sexp as you suggest). I suppose we agree on that. In any case the question is why any defun starters cached before invoking `scan-lists' would be invalid. I can't see a good reason. Can you give me one?. >> And how would a defun start cache handle such constructs? > > Such a cache would be initialised to nil within a particular invocation > of scan-lists, hence nothing like the above could cause any trouble. It's a waste that two subsequent `scan-lists' would not share the same cache but let's stay with this assumption for the rest. > scan-lists is an atomic function, without memory of any state. It's > functionality is wholly determined by the current buffer state and the > current setting of (quite a few) state variables. > > syntax-ppss is motivated by cacheing historical state, hence is > critically different. Then we have to flush its cache when calling `scan-lists'. > OK, I think I see what you're getting at. You're thinking of a cache > which would endure over random buffer changes. The cache I was intending > would be flushed at the beginning of each scan-lists. "What I tell you > three times is true." (Lewis Carroll, The Hunting of the Snark). I was thinking of one cache per buffer that would be produced by parsing from BOB. A second cache would mean to double the overhead for writing and maintaining the respective code. > It's truncated at buffer changes. It doesn't contain any information > which could become stale on any of the other sorts of modifications we've > been talking about, or it isn't used when they could hurt anything. That > this cache has a tightly defined purpose is why it can be robust, whereas > syntax-ppss's cache, being very general purpose, is vulnerable to certain > changes. Which obviously means that we'd have to improve the robustness of the syntax-ppss cache. >> What you're asking for is impossible: > >> (1) You want to base find_defun_start on scan_lists starting at BOB. > > No, on scan_sexps_forward, which (despite the confusing name) is the core > of parse-partial-sexp without its lispy arguments. OK >> This means that you need a function that repeatedly calls >> scan_lists, stopping whenever depth reaches zero and remembers that >> position, returning the last such position before FROM. Such a >> function exists already - it's called `parse-partial-sexp'. > > Yes. Or scan_sexps_forward which is the C core of it. OK >> (2) You want to avoid that function call scan_lists repeatedly by >> caching previously found positions. Such a function exists already >> - it's called `syntax-ppss'. > > I'd have nothing against using syntax-ppss, as long as its cache was > bound to nil for each scan-lists call - except it would cause some > slowdown (compared with a special-purpose cache written in C), since it > goes through the lisp bytecode interpreter. Then we have to provide a C-level interface to that cache which can be used by find_defun_start. >> (3) You want that function to work even if someone changes the syntax >> table or disables `before-change-functions' without flushing its >> cache. Such a function does not exist and never will. > > No, I want that cache to be flushed for each scan-lists call, so that the > first scan of (nearly) the whole buffer will create the cache, and the > other 28 scans will use that cache. This means that we'd have to specify which defun starts to store in that cache and replace the `open-paren-in-column-0-is-defun-start' stuff in find_defun_start by going to the last position stored in that cache. The latter should be trivial but is certainly not suited for Emacs 24.4. The former is less trivial (IMHO) and requires a general solution within the context of `syntax-ppss' which might even mean to move the cache building and flushing parts of the latter to C. martin ^ permalink raw reply [flat|nested] 93+ messages in thread
[parent not found: <jwv61jf2owy.fsf-monnier+emacsbugs@gnu.org>]
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression [not found] ` <jwv61jf2owy.fsf-monnier+emacsbugs@gnu.org> @ 2014-07-03 14:59 ` Stefan Monnier 2014-07-04 18:27 ` Alan Mackenzie 2014-07-04 19:29 ` Alan Mackenzie 1 sibling, 1 reply; 93+ messages in thread From: Stefan Monnier @ 2014-07-03 14:59 UTC (permalink / raw) To: Alan Mackenzie; +Cc: 16526 Hi Alan, Can you try the patch below (for the emacs-24 branch), which tries to make the existing cache in find_defun_start do something useful in the case where find_defun_start returns BEGV? Stefan === modified file 'src/syntax.c' --- src/syntax.c 2014-02-08 05:12:47 +0000 +++ src/syntax.c 2014-07-03 14:57:04 +0000 @@ -530,17 +530,6 @@ { ptrdiff_t opoint = PT, opoint_byte = PT_BYTE; - if (!open_paren_in_column_0_is_defun_start) - { - find_start_value = BEGV; - find_start_value_byte = BEGV_BYTE; - find_start_buffer = current_buffer; - find_start_modiff = MODIFF; - find_start_begv = BEGV; - find_start_pos = pos; - return BEGV; - } - /* Use previous finding, if it's valid and applies to this inquiry. */ if (current_buffer == find_start_buffer /* Reuse the defun-start even if POS is a little farther on. @@ -552,6 +541,13 @@ && MODIFF == find_start_modiff) return find_start_value; + if (!open_paren_in_column_0_is_defun_start) + { + find_start_value = BEGV; + find_start_value_byte = BEGV_BYTE; + goto found; + } + /* Back up to start of line. */ scan_newline (pos, pos_byte, BEGV, BEGV_BYTE, -1, 1); @@ -582,13 +578,14 @@ /* Record what we found, for the next try. */ find_start_value = PT; find_start_value_byte = PT_BYTE; + TEMP_SET_PT_BOTH (opoint, opoint_byte); + + found: find_start_buffer = current_buffer; find_start_modiff = MODIFF; find_start_begv = BEGV; find_start_pos = pos; - TEMP_SET_PT_BOTH (opoint, opoint_byte); - return find_start_value; } \f @@ -841,6 +838,7 @@ else { struct lisp_parse_state state; + bool adjusted = false; lossage: /* We had two kinds of string delimiters mixed up together. Decode this going forwards. @@ -852,6 +850,8 @@ { defun_start = find_defun_start (comment_end, comment_end_byte); defun_start_byte = find_start_value_byte; + if (defun_start != BEGV) + adjusted = true; } do { @@ -860,6 +860,16 @@ comment_end, TYPE_MINIMUM (EMACS_INT), 0, Qnil, 0); defun_start = comment_end; + if (!adjusted) + { + adjusted = true; + find_start_value + = CONSP (state.levelstarts) ? XINT (XCAR (state.levelstarts)) + : state.thislevelstart >= 0 ? state.thislevelstart + : find_start_value; + find_start_value_byte = CHAR_TO_BYTE (find_start_value); + } + if (state.incomment == (comnested ? 1 : -1) && state.comstyle == comstyle) from = state.comstr_start; ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-07-03 14:59 ` Stefan Monnier @ 2014-07-04 18:27 ` Alan Mackenzie 2014-07-04 19:11 ` Stefan Monnier 2014-07-04 19:43 ` Stefan Monnier 0 siblings, 2 replies; 93+ messages in thread From: Alan Mackenzie @ 2014-07-04 18:27 UTC (permalink / raw) To: Stefan Monnier; +Cc: 16526 Hello, Stefan. On Thu, Jul 03, 2014 at 10:59:58AM -0400, Stefan Monnier wrote: > Can you try the patch below (for the emacs-24 branch), which tries to > make the existing cache in find_defun_start do something useful in the > case where find_defun_start returns BEGV? [ patch snipped ] I'm not sure what I'm meant to see, but it has made no perceptible difference to the "slow" invocation of scan-lists. In particular, that invocation took 0.7196781635284424 seconds with the patch, which is "exactly" (near enough) what it took before. > Stefan -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-07-04 18:27 ` Alan Mackenzie @ 2014-07-04 19:11 ` Stefan Monnier 2014-07-04 19:43 ` Stefan Monnier 1 sibling, 0 replies; 93+ messages in thread From: Stefan Monnier @ 2014-07-04 19:11 UTC (permalink / raw) To: Alan Mackenzie; +Cc: 16526 >> Can you try the patch below (for the emacs-24 branch), which tries to >> make the existing cache in find_defun_start do something useful in the >> case where find_defun_start returns BEGV? > [ patch snipped ] > I'm not sure what I'm meant to see, An improvement in performance. > but it has made no perceptible difference to the "slow" invocation of > scan-lists. In particular, that invocation took 0.7196781635284424 > seconds with the patch, which is "exactly" (near enough) what it > took before. Oh well. What he patch does (or should do, at least) is that after a "full scan from BOB", it remembers the last top-level open paren seen, so that if the next back_comment's lossage happens in that same area, we only rescan from that open paren rather than from BOB. If it makes no measurable difference for your case, I see two explanations: - a bug in the patch makes it do something else than what I wanted. - lossage rarely happens more than "once per top-level paren", so the cache is almost never re-used anyway. But since in your case it's a single scan-lists call that's slow and that call only skips one single "sexp", the second explanation seems wrong: you do see several occurrences of lossage (which together cause the slowdown) and yet this is all within the same top-level paren. Stefan ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-07-04 18:27 ` Alan Mackenzie 2014-07-04 19:11 ` Stefan Monnier @ 2014-07-04 19:43 ` Stefan Monnier 2014-07-05 2:23 ` Stefan Monnier 2014-07-05 20:25 ` Alan Mackenzie 1 sibling, 2 replies; 93+ messages in thread From: Stefan Monnier @ 2014-07-04 19:43 UTC (permalink / raw) To: Alan Mackenzie; +Cc: 16526 > I'm not sure what I'm meant to see, but it has made no perceptible > difference to the "slow" invocation of scan-lists. In particular, that > invocation took 0.7196781635284424 seconds with the patch, which is > "exactly" (near enough) what it took before. OK, the initialization needs to be after the "lossage:" label, of course. Try the patch below instead, Stefan === modified file 'src/syntax.c' --- src/syntax.c 2014-02-08 05:12:47 +0000 +++ src/syntax.c 2014-07-04 19:42:50 +0000 @@ -530,17 +530,6 @@ { ptrdiff_t opoint = PT, opoint_byte = PT_BYTE; - if (!open_paren_in_column_0_is_defun_start) - { - find_start_value = BEGV; - find_start_value_byte = BEGV_BYTE; - find_start_buffer = current_buffer; - find_start_modiff = MODIFF; - find_start_begv = BEGV; - find_start_pos = pos; - return BEGV; - } - /* Use previous finding, if it's valid and applies to this inquiry. */ if (current_buffer == find_start_buffer /* Reuse the defun-start even if POS is a little farther on. @@ -550,7 +539,20 @@ && pos >= find_start_value && BEGV == find_start_begv && MODIFF == find_start_modiff) + { + if (!open_paren_in_column_0_is_defun_start) + fprintf (stderr, "Optimized lossage by %d (%d%%)!\n", + find_start_value - BEGV, + 100 * (find_start_value - BEGV) / (pos - BEGV)); return find_start_value; + } + + if (!open_paren_in_column_0_is_defun_start) + { + find_start_value = BEGV; + find_start_value_byte = BEGV_BYTE; + goto found; + } /* Back up to start of line. */ scan_newline (pos, pos_byte, BEGV, BEGV_BYTE, -1, 1); @@ -582,13 +584,14 @@ /* Record what we found, for the next try. */ find_start_value = PT; find_start_value_byte = PT_BYTE; + TEMP_SET_PT_BOTH (opoint, opoint_byte); + + found: find_start_buffer = current_buffer; find_start_modiff = MODIFF; find_start_begv = BEGV; find_start_pos = pos; - TEMP_SET_PT_BOTH (opoint, opoint_byte); - return find_start_value; } \f @@ -841,7 +844,9 @@ else { struct lisp_parse_state state; + bool adjusted; lossage: + adjusted = false; /* We had two kinds of string delimiters mixed up together. Decode this going forwards. Scan fwd from a known safe place (beginning-of-defun) @@ -852,6 +857,8 @@ { defun_start = find_defun_start (comment_end, comment_end_byte); defun_start_byte = find_start_value_byte; + if (defun_start != BEGV) + adjusted = true; } do { @@ -860,6 +867,16 @@ comment_end, TYPE_MINIMUM (EMACS_INT), 0, Qnil, 0); defun_start = comment_end; + if (!adjusted) + { + adjusted = true; + find_start_value + = CONSP (state.levelstarts) ? XINT (XCAR (state.levelstarts)) + : state.thislevelstart >= 0 ? state.thislevelstart + : find_start_value; + find_start_value_byte = CHAR_TO_BYTE (find_start_value); + } + if (state.incomment == (comnested ? 1 : -1) && state.comstyle == comstyle) from = state.comstr_start; ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-07-04 19:43 ` Stefan Monnier @ 2014-07-05 2:23 ` Stefan Monnier 2014-07-06 13:48 ` Alan Mackenzie 2014-07-05 20:25 ` Alan Mackenzie 1 sibling, 1 reply; 93+ messages in thread From: Stefan Monnier @ 2014-07-05 2:23 UTC (permalink / raw) To: Alan Mackenzie; +Cc: 16526 > OK, the initialization needs to be after the "lossage:" label, > of course. Try the patch below instead, Well, I installed the patch since it does speed up my test case noticeably (M-> followed by <prior> <prior> in src/xdisp.c). I do have a question about open-paren-in-column-0-is-defun-start: why do you let-bind it at various places instead of setting it buffer-locally once and for all. I see you had such a buffer-local setting but that you commented it out in 2006/12/17. Do you remember what was the reason for it? From my naive point of view a buffer-local setting would not only be simpler but would also be better for the user who could more easily set it back to non-nil if she wanted to. Stefan ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-07-05 2:23 ` Stefan Monnier @ 2014-07-06 13:48 ` Alan Mackenzie 2014-07-07 1:52 ` Stefan Monnier ` (2 more replies) 0 siblings, 3 replies; 93+ messages in thread From: Alan Mackenzie @ 2014-07-06 13:48 UTC (permalink / raw) To: Stefan Monnier, martin rudalics; +Cc: 16526 Hello, Stefan. On Fri, Jul 04, 2014 at 10:23:07PM -0400, Stefan Monnier wrote: > > OK, the initialization needs to be after the "lossage:" label, > > of course. Try the patch below instead, > Well, I installed the patch since it does speed up my test case > noticeably (M-> followed by <prior> <prior> in src/xdisp.c). Excellent! Hello, Martin, how far does this patch go, from your point of view, in solving the sluggishness in xdisp.c? > I do have a question about open-paren-in-column-0-is-defun-start: why do > you let-bind it at various places instead of setting it buffer-locally > once and for all. Misunderstanding/lack of documentation. My aim was to restrict the effect of binding open-paren-etc to nil to its supposed "subsidiary" effects in scan-lists, leaving the "main" higher level effects unchanged from the user's setting (or lack thereof). > I see you had such a buffer-local setting but that you commented it out > in 2006/12/17. Do you remember what was the reason for it? I've had a look at the thread "Mysterious fontification/C++ context issue - Patch for beginning-of-defun-raw." in emacs-devel which started around 2006-12-04. It's long and rambling and most of the posts are heavily context dependent, making it difficult to follow. > >>From my naive point of view a buffer-local setting would not only be > simpler but would also be better for the user who could more easily set > it back to non-nil if she wanted to. How about going back to Martin's suggestion, and letting the user decide on the variable's setting? Trouble is, open-paren-etc's system-wide default is t, whereas here it really wants to be nil - parens which just happen to be in column 0 are not that uncommon. The crude way would be to introduce c-open-paren-in-column-0-is-defun-start, but this has problems of its own. How, in general, can we cleanly give a user option a mode specific default? > Stefan -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-07-06 13:48 ` Alan Mackenzie @ 2014-07-07 1:52 ` Stefan Monnier 2014-07-07 7:07 ` martin rudalics [not found] ` <jwvsimevsvz.fsf-monnier+emacsbugs@gnu.org> 2 siblings, 0 replies; 93+ messages in thread From: Stefan Monnier @ 2014-07-07 1:52 UTC (permalink / raw) To: Alan Mackenzie; +Cc: 16526 > How about going back to Martin's suggestion, and letting the user decide > on the variable's setting? That's exactly why I'm bringing this up: what was wrong with setting it buffer-locally in the major-mode function? > problems of its own. How, in general, can we cleanly give a user option > a mode specific default? As above. If the user doesn't like this mode-provided setting, she could easily override it with (add-hook 'c-mode-hook (lambda () (setq-local open-paren-in-column-0-is-defun-start t))) -- Stefan ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-07-06 13:48 ` Alan Mackenzie 2014-07-07 1:52 ` Stefan Monnier @ 2014-07-07 7:07 ` martin rudalics [not found] ` <jwvsimevsvz.fsf-monnier+emacsbugs@gnu.org> 2 siblings, 0 replies; 93+ messages in thread From: martin rudalics @ 2014-07-07 7:07 UTC (permalink / raw) To: Alan Mackenzie, Stefan Monnier; +Cc: 16526 > Hello, Martin, how far does this patch go, from your point of view, in > solving the sluggishness in xdisp.c? FWIW the improvement is considerable and the performance doesn't seem worse now than with `open-paren-in-column-0-is-defun-start' non-nil. So from what I can tell here at the moment this issue seems resolved. Thanks to Stefan and you, martin ^ permalink raw reply [flat|nested] 93+ messages in thread
[parent not found: <jwvsimevsvz.fsf-monnier+emacsbugs@gnu.org>]
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression [not found] ` <jwvsimevsvz.fsf-monnier+emacsbugs@gnu.org> @ 2014-07-07 7:07 ` martin rudalics 0 siblings, 0 replies; 93+ messages in thread From: martin rudalics @ 2014-07-07 7:07 UTC (permalink / raw) To: Stefan Monnier, Alan Mackenzie; +Cc: 16526 > As above. If the user doesn't like this mode-provided setting, she could > easily override it with > > (add-hook 'c-mode-hook > (lambda () > (setq-local open-paren-in-column-0-is-defun-start t))) My c-mode-hook contains (set (make-local-variable 'open-paren-in-column-0-is-defun-start) t) but this ceased to work after Alan's changes. martin ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-07-04 19:43 ` Stefan Monnier 2014-07-05 2:23 ` Stefan Monnier @ 2014-07-05 20:25 ` Alan Mackenzie 2014-07-05 23:06 ` Stefan Monnier 1 sibling, 1 reply; 93+ messages in thread From: Alan Mackenzie @ 2014-07-05 20:25 UTC (permalink / raw) To: Stefan Monnier; +Cc: 16526 Hi, Stefan. On Fri, Jul 04, 2014 at 03:43:02PM -0400, Stefan Monnier wrote: > > I'm not sure what I'm meant to see, but it has made no perceptible > > difference to the "slow" invocation of scan-lists. In particular, that > > invocation took 0.7196781635284424 seconds with the patch, which is > > "exactly" (near enough) what it took before. > OK, the initialization needs to be after the "lossage:" label, > of course. Try the patch below instead, This works considerably better. :-) The critical scan-lists took 0.12084102630615234 seconds, a speedup of a factor of ~7. It may be even larger than that because of the instrumentation in the patch. CC Mode has a problem in that it does too many backward scan-lists. There is no documentation anywhere of what open-paren-in-column-0-etc does; its sole effect is in backwards scan-lists which encounter "syntactically unbalanced" comments, this causing a scan of the buffer from point-min. When I optimised c-parse-state a few years back, I was under the impression that a backwards scan-lists wasn't much more expensive than a forwards one. Often, this is not true. I should think about adjusting c-parse-state again. It surely wouldn't hurt for the documentation of open-paren-etc and scan-lists to be a bit more forthcoming about backwards scan-listses and what the variable _really_ does. > Stefan -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-07-05 20:25 ` Alan Mackenzie @ 2014-07-05 23:06 ` Stefan Monnier 0 siblings, 0 replies; 93+ messages in thread From: Stefan Monnier @ 2014-07-05 23:06 UTC (permalink / raw) To: Alan Mackenzie; +Cc: 16526 > from point-min. When I optimised c-parse-state a few years back, I was > under the impression that a backwards scan-lists wasn't much more > expensive than a forwards one. Often, this is not true. Indeed. Programming language syntax is designed to be parsed forward, so parsing it backward can sometimes be surprisingly difficult. > about adjusting c-parse-state again. It surely wouldn't hurt for the > documentation of open-paren-etc and scan-lists to be a bit more > forthcoming about backwards scan-listses and what the variable _really_ > does. I think open-paren-in-column-0-is-defun-start is on the way out, FWIW. `syntax-ppss' makes is largely irrelevant. Stefan ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression [not found] ` <jwv61jf2owy.fsf-monnier+emacsbugs@gnu.org> 2014-07-03 14:59 ` Stefan Monnier @ 2014-07-04 19:29 ` Alan Mackenzie 2014-07-05 1:52 ` Stefan Monnier 1 sibling, 1 reply; 93+ messages in thread From: Alan Mackenzie @ 2014-07-04 19:29 UTC (permalink / raw) To: Stefan Monnier; +Cc: 16526-done Hi, Stefan. On Wed, Jul 02, 2014 at 09:57:23PM -0400, Stefan Monnier wrote: > > No. The particular rogue invocation of scan-lists which caused this > > (sub-)thread scans from BOB to near EOB 29 times. Inside scan-lists, > > _NO_ changes to syntax-tables, s-t text properties etc. are possible. > > What I'm suggesting is that cacheing that first scan from BOB will be a > > big win for many time-consuming scan-listses. > Here's the situation: we can add some special code to handle your case. > But adding code which will use syntax-ppss would be more beneficial for > 99% of the major modes. My suggestion is less radical, in that it leaves the functionality of scan-lists unchanged. It's speedup may be indistinguishable from the strategy of simply using syntax-ppss. > Adding a cache that only works within a single scan-lists instance is > too much trouble for too little gain. Modulo a binding to nil (or two), it could be the same code as that which simply uses the existing syntax-ppss cache. Without trying it, we don't know how big or little the gain is. > Adding a cache that is flushed less often means either it will suffer > from the same limitations as syntax-ppss (so we may as well use > syntax-ppss), or it needs to additionally hook into the text-property > and set-syntax-table code to be flushed in those extra corner cases, > and there again these extra checks will be only useful for those rare > modes like CC-mode and will be at best harmless and in some cases > detrimental to performance compared to simply using syntax-ppss. Yes, to all of that, except I doubt the performance penalty in the last bit would be noticeable (it'd be in C code, surely?). > IOW, using syntax-ppss for find_defun_start is The Right Thing to do. It is the route of least effort, perhaps, which is important. It will give suboptimal results for modes where syntax-ppss's basic assumptions don't hold. But this is also true of the exising scan-lists, so isn't, perhaps, too important. As a matter of interest, is there an existing mechanism for calling lisp from random bits of the C code? > And CC-mode should then be fixed to take advantage of it. It being syntax-ppss. What CC Mode frequently needs to know is whether a given position is in a comment, string, preprocessor construct, or other code. parse-partial-sexp and syntax-ppss don't give enough information for this, hence aren't used for this directly. A long term solution may be to enhance the syntax bits of Emacs to recognise "syntactic islands" (e.g. C preprocessor construct, shell script "here documents" or literate programming chunks) somehow. > Stefan -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-07-04 19:29 ` Alan Mackenzie @ 2014-07-05 1:52 ` Stefan Monnier 2014-07-05 7:47 ` Alan Mackenzie 0 siblings, 1 reply; 93+ messages in thread From: Stefan Monnier @ 2014-07-05 1:52 UTC (permalink / raw) To: Alan Mackenzie; +Cc: 16526-done > A long term solution may be to enhance the syntax bits of Emacs to > recognise "syntactic islands" (e.g. C preprocessor construct, shell > script "here documents" or literate programming chunks) somehow. Shell script's here-documents work just fine when considered as comments. Literate programming also works well when considering the non-code as comments. Maybe the same would hold of CPP thingies. Stefan ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-07-05 1:52 ` Stefan Monnier @ 2014-07-05 7:47 ` Alan Mackenzie 0 siblings, 0 replies; 93+ messages in thread From: Alan Mackenzie @ 2014-07-05 7:47 UTC (permalink / raw) To: Stefan Monnier; +Cc: 16526-done Hi, Stefan. On Fri, Jul 04, 2014 at 09:52:09PM -0400, Stefan Monnier wrote: > > A long term solution may be to enhance the syntax bits of Emacs to > > recognise "syntactic islands" (e.g. C preprocessor construct, shell > > script "here documents" or literate programming chunks) somehow. > Shell script's here-documents work just fine when considered > as comments. Literate programming also works well when considering the > non-code as comments. > Maybe the same would hold of CPP thingies. Except that the "commented out" bits have their own syntactic structure. Ideally, a shell script here document as argument to awk ought to be parsed in AWK Mode. The non-code bits of literate programming are also likely to have their own structure. CPP sections are handled as C/C++/ObjC, but the complication caused by keeping them separate from the main code are considerable. > Stefan -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression [not found] ` <20140629144151.GD2948@acm.acm> 2014-06-29 16:01 ` martin rudalics [not found] ` <53B03876.9070307@gmx.at> @ 2014-06-29 22:14 ` Stefan Monnier [not found] ` <jwvionjjrn7.fsf-monnier+emacsbugs@gnu.org> 3 siblings, 0 replies; 93+ messages in thread From: Stefan Monnier @ 2014-06-29 22:14 UTC (permalink / raw) To: Alan Mackenzie; +Cc: 16526-done > scan-lists, a primitive, must be utterly robust. syntax-ppss is too > fragile to be used here without a lot of hardening. FWIW, CC-mode is one of the last remaining major modes (at least the only one I know of that's bundled with Emacs) that doesn't play nice with syntax-ppss. Incidentally, AFAIK it's also the only code which uses font-lock-extend-after-change-region-function (and yes, I think the two are (indirectly) related). > If one were to harden syntax-ppss against all these things, one would > probably end up calculating the cache from scratch every time, in effect. Exactly. IOW a cache can only be robust if the major mode plays by the rules, which cc-mode doesn't do. Stefan ^ permalink raw reply [flat|nested] 93+ messages in thread
[parent not found: <jwvionjjrn7.fsf-monnier+emacsbugs@gnu.org>]
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression [not found] ` <jwvionjjrn7.fsf-monnier+emacsbugs@gnu.org> @ 2014-07-02 18:40 ` Alan Mackenzie [not found] ` <20140702184013.GA3823@acm.acm> 1 sibling, 0 replies; 93+ messages in thread From: Alan Mackenzie @ 2014-07-02 18:40 UTC (permalink / raw) To: Stefan Monnier; +Cc: 16526-done Hello, Stefan. On Sun, Jun 29, 2014 at 06:14:45PM -0400, Stefan Monnier wrote: > > scan-lists, a primitive, must be utterly robust. syntax-ppss is too > > fragile to be used here without a lot of hardening. > FWIW, CC-mode is one of the last remaining major modes (at least the > only one I know of that's bundled with Emacs) that doesn't play nice > with syntax-ppss. Doesn't it? First I've heard of it. Though of course, what comes out of syntax-ppss is going to be of limited value when you've got lines like this in your source: #define FOO BAR /* accidentally unclosed comment. Just as a matter of interest, what code is there around which wants to use syntax-ppss on a CC Mode buffer? > Incidentally, AFAIK it's also the only code which uses > font-lock-extend-after-change-region-function .... Is that right? Well, what do you know! Still, it's a good facility to have around for when it's needed. It avoids the need to have to advise font-lock after change functions, whilst still doing fontification right. > .... (and yes, I think the two are (indirectly) related). Well, everything's related to everything else, more or less indirectly. Do you think there's any significance to this indirect relationship? > > If one were to harden syntax-ppss against all these things, one would > > probably end up calculating the cache from scratch every time, in effect. > Exactly. IOW a cache can only be robust if the major mode plays by the > rules, which cc-mode doesn't do. CC Mode does what it has to do to do its job. As you yourself, amongst others, have remarked, CC Mode deals with utter bastards of languages. Its caches are quite capable of being robust. I'm not convinced that syntax-ppss is capable of being robust. Some of its shortcomings are listed in syntax.el. > Stefan -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 93+ messages in thread
[parent not found: <20140702184013.GA3823@acm.acm>]
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression [not found] ` <20140702184013.GA3823@acm.acm> @ 2014-07-02 19:40 ` Stefan Monnier 0 siblings, 0 replies; 93+ messages in thread From: Stefan Monnier @ 2014-07-02 19:40 UTC (permalink / raw) To: Alan Mackenzie; +Cc: 16526-done >> FWIW, CC-mode is one of the last remaining major modes (at least the >> only one I know of that's bundled with Emacs) that doesn't play nice >> with syntax-ppss. > Doesn't it? First I've heard of it. Well, I go by what you said: No, syntax-ppss wouldn't do here without considerable modification. > Though of course, what comes out of syntax-ppss is going to be of > limited value when you've got lines like this in your source: > > #define FOO BAR /* accidentally unclosed comment. Yes, sometimes you need to be a bit creative to get syntax-ppss to behave. But so far, I've always managed to coerce it acceptably. > Just as a matter of interest, what code is there around which wants to > use syntax-ppss on a CC Mode buffer? It's used by various obscure packages like font-lock, newcomment, ... >> Incidentally, AFAIK it's also the only code which uses >> font-lock-extend-after-change-region-function .... > Is that right? Well, what do you know! Still, it's a good facility to > have around for when it's needed. It avoids the need to have to advise > font-lock after change functions, whilst still doing fontification right. Other packages manage to do it right without it. As soon as CC-mode is changed to use syntax-propertize-function, I expect that it won't use font-lock-extend-after-change-region-function any longer. > CC Mode does what it has to do to do its job. As you yourself, amongst > others, have remarked, CC Mode deals with utter bastards of languages. > Its caches are quite capable of being robust. I'm not convinced that > syntax-ppss is capable of being robust. Some of its shortcomings are > listed in syntax.el. I don't think there's much point in comparing the track record of caching bugs in syntax.el compared to cc-mode. Stefan ^ permalink raw reply [flat|nested] 93+ messages in thread
[parent not found: <jwvsimpksv1.fsf-monnier+emacsbugs@gnu.org>]
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression [not found] ` <jwvsimpksv1.fsf-monnier+emacsbugs@gnu.org> @ 2014-06-28 17:33 ` Alan Mackenzie [not found] ` <20140628173334.GB2632@acm.acm> 1 sibling, 0 replies; 93+ messages in thread From: Alan Mackenzie @ 2014-06-28 17:33 UTC (permalink / raw) To: Stefan Monnier; +Cc: 16526-done Hi, Stefan. On Sat, Jun 28, 2014 at 10:34:58AM -0400, Stefan Monnier wrote: > > Where do we go from here? > Not sure. Would `syntax-ppss' return correct values from the code in > question? If yes, then changing back_comment to call back to Elisp and > use syntax-ppss in the lossage case should eliminate this > algorithmic problem. No, syntax-ppss wouldn't do here without considerable modification. scan-lists must be utterly robust. syntax-ppss can get confused if the user changes the syntax-table, or adds systax-table text properties, or binds before-change-functions to nil and makes a change. How about simply (tm) find-defun-start actually determining a defun start (when open-paren-..-defun is nil) the first time it is called for an invocation of scan-lists, then remembering this position for subsequent use? This would work well for the particular scan-lists invocation we've been talking about. As an enhancement, which would work well for scan-lists at top level with a large negative COUNT, we could keep a list of top level positions during the initial scan, say every ~5k characters. (Or even store the actual parse states every 5k characters exactly.) Or something like that. > Stefan -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 93+ messages in thread
[parent not found: <20140628173334.GB2632@acm.acm>]
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression [not found] ` <20140628173334.GB2632@acm.acm> @ 2014-06-29 21:39 ` Stefan Monnier 0 siblings, 0 replies; 93+ messages in thread From: Stefan Monnier @ 2014-06-29 21:39 UTC (permalink / raw) To: Alan Mackenzie; +Cc: 16526-done > No, syntax-ppss wouldn't do here without considerable modification. Why? > scan-lists must be utterly robust. syntax-ppss can get confused if the > user changes the syntax-table, Indeed, the user shouldn't change the syntax-table ;-) > or adds systax-table text properties, The user should do that via syntax-propertize. > or binds before-change-functions to nil and makes a change. User gets what she deserves. Binding inhibit-modification-hooks while making changes is dangerous, but binding before-change-functions to nil is simply evil and asking for trouble. > How about simply (tm) find-defun-start actually determining a defun > start (when open-paren-..-defun is nil) the first time it is called for > an invocation of scan-lists, then remembering this position for > subsequent use? That's indeed what syntax-ppss would do. But if the syntax-table may change (or added as text-properties, or if before-change-functions is let-bound to nil while making modifications), any such mechanism is bound to fail because in those cases it shouldn't "remember this position for subsequent use". > As an enhancement, which would work well for scan-lists at top level > with a large negative COUNT, we could keep a list of top level positions > during the initial scan, say every ~5k characters. (Or even store the > actual parse states every 5k characters exactly.) You're describing syntax-ppss. Stefan ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-01-26 17:20 ` Eli Zaretskii 2014-01-26 20:43 ` Alan Mackenzie @ 2014-01-27 8:20 ` martin rudalics 2014-01-27 16:23 ` Eli Zaretskii 1 sibling, 1 reply; 93+ messages in thread From: martin rudalics @ 2014-01-27 8:20 UTC (permalink / raw) To: Eli Zaretskii; +Cc: acm, 16526 > After beginning-of-buffer jumps to point-min, redisplay kicks in. > Since scroll-conservatively is set to a large value, redisplay first > tries to see whether it can bring point into view by scrolling the > window as little as possible. It calls try_scrolling, which at some > point (around line 15000) tries to see whether the new location of > point is close enough to the current window start. It does so by > calling move_it_to, which simulates the display. While doing so, > move_it_to hits a portion of text with font-lock properties, and calls > JIT Lock to fontify them. Well... try_scrolling could detect that `point' is some 15000 lines away from the current window start so trying to scroll the window as little as possible might not be worth the effort. > And here's where things go awry: For some reason, the CC Mode > fontification code decides it needs to scan the buffer backwards, > starting from EOB. So it goes temporarily to EOB (this is why I saw > point being there), and scans all the way back, I think in this loop > from c-append-lower-brace-pair-to-state-cache, which is called with > its first argument FROM set to EOB: But it's redisplay which temporarily puts `point' at EOB and triggers the fontification subsystem to "work" at that position? > This loop takes a lot of time, of course, and is a waste of time, > since eventually try_scrolling comes to the correct conclusion that > scrolling is impossible, and instead recenters at BOB. Are you sure that try_scrolling doesn't call this loop over and over again? > Why does CC Mode decide to go from EOB backwards, I don't know; > presumably, this is decided by c-parse-state-get-strategy as part of > c-parse-state-1. This seems obvious. To decide whether code shall be fontified this way or another it has to decide whether the code is part of a comment and find that comment's start. As long as it is not aware of the fact that `point' is already at BOB, obviously. martin ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-01-27 8:20 ` martin rudalics @ 2014-01-27 16:23 ` Eli Zaretskii 2014-01-27 17:26 ` martin rudalics 0 siblings, 1 reply; 93+ messages in thread From: Eli Zaretskii @ 2014-01-27 16:23 UTC (permalink / raw) To: martin rudalics; +Cc: acm, 16526 > Date: Mon, 27 Jan 2014 09:20:57 +0100 > From: martin rudalics <rudalics@gmx.at> > CC: acm@muc.de, 16526@debbugs.gnu.org > > Well... try_scrolling could detect that `point' is some 15000 lines away > from the current window start so trying to scroll the window as little > as possible might not be worth the effort. How would it detect that, except using the same method it uses now? Note that we are not talking physical lines in the buffer here, we are talking screen lines. Actually, not even that: we are talking _canonical_ screen lines, i.e. practically pixels. Now, those 15000 lines could well be covered by an invisible property, or by a display property that displays something other than buffer text. Or they could use a face that calls for a very small font, so that all the 15000 lines take very little screen estate. In all of these cases, a user who sets scroll-conservatively to 101 wants the screen scrolled rather than recentered. So that's what try_scrolling tries to do. It's why that function exists. However, try_scrolling's search is limited, so it normally fails very quickly. Except that in this case, the code invoked by JIT Lock hogs the CPU for a very long time. > > And here's where things go awry: For some reason, the CC Mode > > fontification code decides it needs to scan the buffer backwards, > > starting from EOB. So it goes temporarily to EOB (this is why I saw > > point being there), and scans all the way back, I think in this loop > > from c-append-lower-brace-pair-to-state-cache, which is called with > > its first argument FROM set to EOB: > > But it's redisplay which temporarily puts `point' at EOB and triggers > the fontification subsystem to "work" at that position? No, redisplay doesn't change point, not ever. It's cc-engine's routines that do it in this case, and I've shown where in the code that happens, see the backtrace I posted. > > This loop takes a lot of time, of course, and is a waste of time, > > since eventually try_scrolling comes to the correct conclusion that > > scrolling is impossible, and instead recenters at BOB. > > Are you sure that try_scrolling doesn't call this loop over and over > again? Sorry, I don't understand the question. try_scrolling doesn't include any loops where all this happens, it just calls move_it_to, a single call. All the rest happens inside that call. Normally, that call should just descend a few screen lines starting at point (which is at BOB), until it hits the limit I mentioned above, and then try_scrolling should return a failure indication. I did verify that there's a single call to move_it_to, and that all the time you wait is spent inside that call. > > Why does CC Mode decide to go from EOB backwards, I don't know; > > presumably, this is decided by c-parse-state-get-strategy as part of > > c-parse-state-1. > > This seems obvious. To decide whether code shall be fontified this way > or another it has to decide whether the code is part of a comment and > find that comment's start. As long as it is not aware of the fact that > `point' is already at BOB, obviously. Why shouldn't CC Mode be aware that point is at BOB? It has just to look at its value. ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-01-27 16:23 ` Eli Zaretskii @ 2014-01-27 17:26 ` martin rudalics 0 siblings, 0 replies; 93+ messages in thread From: martin rudalics @ 2014-01-27 17:26 UTC (permalink / raw) To: Eli Zaretskii; +Cc: acm, 16526 > How would it detect that, except using the same method it uses now? > Note that we are not talking physical lines in the buffer here, we are > talking screen lines. Actually, not even that: we are talking > _canonical_ screen lines, i.e. practically pixels. Now, those 15000 > lines could well be covered by an invisible property, or by a display > property that displays something other than buffer text. Or they > could use a face that calls for a very small font, so that all the > 15000 lines take very little screen estate. In all of these cases, a > user who sets scroll-conservatively to 101 wants the screen scrolled > rather than recentered. So that's what try_scrolling tries to do. > It's why that function exists. At least now I understand why setting `scroll-conservatively' to 101 can be expensive. >> But it's redisplay which temporarily puts `point' at EOB and triggers >> the fontification subsystem to "work" at that position? > > No, redisplay doesn't change point, not ever. It's cc-engine's > routines that do it in this case, and I've shown where in the code > that happens, see the backtrace I posted. I see. Fontification routines just get the boundaries they have to operate on. The backtrace is difficult to interpret - I never know which of Alan's macros save excursion. But since it returns a buffer position it likely that it reuses that position later on. >> Are you sure that try_scrolling doesn't call this loop over and over >> again? > > Sorry, I don't understand the question. try_scrolling doesn't include > any loops where all this happens, it just calls move_it_to, a single > call. All the rest happens inside that call. Normally, that call > should just descend a few screen lines starting at point (which is at > BOB), until it hits the limit I mentioned above, and then > try_scrolling should return a failure indication. > > I did verify that there's a single call to move_it_to, and that all > the time you wait is spent inside that call. I just wanted to make sure that there's no loop in try_scrolling. > Why shouldn't CC Mode be aware that point is at BOB? It has just to > look at its value. It shouldn't matter anyway since, as you said above, the display engine never sets point. Thanks for the clarifications. My questions were naive because I never looked into how scrolling works and moreover do not understand c-mode macros well. martin ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression 2014-01-25 18:31 ` Eli Zaretskii 2014-01-25 18:40 ` Eli Zaretskii @ 2014-01-26 11:19 ` martin rudalics 1 sibling, 0 replies; 93+ messages in thread From: martin rudalics @ 2014-01-26 11:19 UTC (permalink / raw) To: Eli Zaretskii; +Cc: acm, 16526 >> IIUC `beginning-of-buffer' does set_point_both. Does that move all the >> way back to the beginning? > > Of course not, it jumps there in one go. > >> > And yes, I know why: it's because scroll-conservatively causes >> > redisplay to examine buffer text around point, >> >> Where is `point' at that time? > > At EOB. But if `beginning-of-buffer' jumps to BOB in one go how comes that `point' at the time something "causes redisplay to examine buffer text around point" is still at EOB? >> But the `end-of-buffer' call terminates cleanly after a few seconds - >> that's what the `sit-for' proves in my code. > > Right, and that's when redisplay kicks in, which invokes JIT Lock. If I shorten my scenario to (progn (setq scroll-conservatively 101) (find-file (concat source-directory "src/xdisp.c")) (end-of-buffer) (sit-for 3)) it terminates here in a few seconds. When/where exactly does redisplay kick in in the original scenario? >> > No, going to BOB is instantaneous. The problem happens in redisplay >> > after going to EOB. >> >> EOB happens before my `sit-for'. > > See above. Redisplay is separate from command execution. So yes, we > are already at EOB, and then redisplay happens. And I see nothing bad happen until that redisplay finishes. >> >> And somehow a "current position" is still near the end of the buffer at >> >> that time. >> > >> > Yes, because Emacs is at EOB. >> >> Why? > > Because we moved there with end-of-buffer. And then `beginning-of-buffer' moves `point' to `point-min' and the trouble starts. We probably are miscommunicating but please check once more your claim that the problem is with redisplay after `end-of-buffer'. If I omit `beginning-of-buffer' from my code I can see no problems. martin ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression. The purpose of revision 116070. [not found] ` <52E3D131.2090705@gmx.at> 2014-01-25 16:30 ` Eli Zaretskii @ 2014-01-25 20:27 ` Alan Mackenzie [not found] ` <20140125202721.GA3630@acm.acm> 2 siblings, 0 replies; 93+ messages in thread From: Alan Mackenzie @ 2014-01-25 20:27 UTC (permalink / raw) To: martin rudalics, Eli Zaretskii; +Cc: 16526 Hello, Martin and Eli. On Sat, Jan 25, 2014 at 03:58:57PM +0100, martin rudalics wrote: > > Probably. I actually don't understand how come scroll-conservatively > > affects non-scrolling commands. Can you elaborate on that? > How should I know? I suppose redisplay_window eventually winds up > calling the fontification function and sooner or later the c-code calls > back_comment. Yes. > > You also mentioned back_comment doing something unreasonable. Can you > > expand on that, too? This part specifically I don't understand: > >> What happens is that apparently back_comment 530 times scans the buffer > >> from the beginning of the buffer to the first comment before the current > >> position where the list of current positions goes like this: > > Since the problem happens as result of beginning-of-buffer, why would > > back_comment need to "scan the buffer from the beginning of the buffer > > to the first comment before the current position"? And what is the > > current position in this case? > I earlier posted the first and last positions here: > (780 14143 15852 18026 20032 20480 21464 21846 22845 23484 25453 26968 > ... > 942907 943099 944334 948653 948830 948653 948830 948653 948830 948653 > 948830 780 12) > You can try by yourself. I gathered the positions in the following > excerpt > find_defun_start (ptrdiff_t pos, ptrdiff_t pos_byte) > { > ptrdiff_t opoint = PT, opoint_byte = PT_BYTE; > if (!open_paren_in_column_0_is_defun_start) > { > find_start_value = BEGV; > find_start_value_byte = BEGV_BYTE; > find_start_buffer = current_buffer; > find_start_modiff = MODIFF; > find_start_begv = BEGV; > find_start_pos = pos; > <---------------------------- right here > return BEGV; > } > > Btw, if I disable font-lock ("M-x global-font-lock-mode RET") before > > repeating the recipe, the move to bob is instantaneous, and turning on > > font-lock after that doesn't seem to have any adverse effects on > > responsiveness. > Sure. The problem happens obviously via jit-lock. But IMHO disabling > `open-paren-in-column-0-is-defun-start' IS asking for trouble as long as > back_comment doesn't rely on `syntax-ppss' to find a safe position. The reason I disabled open-paren-etc. was a bug report from Michael Welsh Duggan, where commented out code was causing the CC Mode "state cache" to get corrupted. The critical bit of his source looks like this (note the commenting out at L3): 1. #define PARTIAL_MD5_SIZE 4096 2. 3. /* 4. 5. TODO: Partial sums (for working with very large files). 6. 7. typedef struct _signature 8. { 9. md5_state_t state; 10. md5_byte_t digest[16]; 11. } signature_t; 12. 13. typedef struct _signatures 14. { 15. int num_signatures; 16. signature_t *signatures; 17. } signatures_t; 18. 19. */ 20. 21. typedef struct _file { With pos at BOL21, (scan-lists pos -1 -1) was returning BOL17. It was ignoring the commenting out. Fscan_lists calls scan_lists which calls back_comment. Because open-paren-etc. was t, back_comment was tripping up on the brace at BOL14 and thus not recognising the comment at all. The "solution" to the bug was to bind open-paren-etc. to nil around the critical code. This is almost certainly what is causing the slow down. Though for some reason, I don't see this slow down myself. This is quite worrying. I am using an up-to-date (as of yesterday evening) bzr Emacs and following your (Martin's) recipe by yanking it into a buffer and doing C-x C-e on it. If I've understood correctly, I think the root cause of the slowness is the lack of optimisation of find_defun_start when open-paren-etc. is nil - it brutally returns BOB, no matter what. Perhaps some sort of cache of safe positions (doesn't one exist already?) could accelerate find_defun_start to acceptable speed in this use case. > martin -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 93+ messages in thread
[parent not found: <20140125202721.GA3630@acm.acm>]
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression. The purpose of revision 116070. [not found] ` <20140125202721.GA3630@acm.acm> @ 2014-01-25 23:02 ` Stefan Monnier 2014-01-26 3:41 ` Eli Zaretskii 2014-01-26 17:35 ` Eli Zaretskii 2 siblings, 0 replies; 93+ messages in thread From: Stefan Monnier @ 2014-01-25 23:02 UTC (permalink / raw) To: Alan Mackenzie; +Cc: 16526 > - it brutally returns BOB, no matter what. Perhaps some sort of cache of > safe positions (doesn't one exist already?) could accelerate > find_defun_start to acceptable speed in this use case. syntax-ppss maintains such a cache. But it's in Elisp. Stefan ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression. The purpose of revision 116070. [not found] ` <20140125202721.GA3630@acm.acm> 2014-01-25 23:02 ` Stefan Monnier @ 2014-01-26 3:41 ` Eli Zaretskii 2014-01-26 9:54 ` Alan Mackenzie 2014-01-26 17:35 ` Eli Zaretskii 2 siblings, 1 reply; 93+ messages in thread From: Eli Zaretskii @ 2014-01-26 3:41 UTC (permalink / raw) To: Alan Mackenzie; +Cc: 16526 > Date: Sat, 25 Jan 2014 20:27:21 +0000 > Cc: 16526@debbugs.gnu.org > From: Alan Mackenzie <acm@muc.de> > > Though for some reason, I don't see this slow down myself. This is quite > worrying. I am using an up-to-date (as of yesterday evening) bzr Emacs > and following your (Martin's) recipe by yanking it into a buffer and > doing C-x C-e on it. How do you configure your build? Can you show the exact configure and make commands you use? ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression. The purpose of revision 116070. 2014-01-26 3:41 ` Eli Zaretskii @ 2014-01-26 9:54 ` Alan Mackenzie 2014-01-26 16:33 ` Eli Zaretskii 0 siblings, 1 reply; 93+ messages in thread From: Alan Mackenzie @ 2014-01-26 9:54 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 16526 Hi, Eli. On Sun, Jan 26, 2014 at 05:41:12AM +0200, Eli Zaretskii wrote: > > Date: Sat, 25 Jan 2014 20:27:21 +0000 > > Cc: 16526@debbugs.gnu.org > > From: Alan Mackenzie <acm@muc.de> > > Though for some reason, I don't see this slow down myself. This is quite > > worrying. I am using an up-to-date (as of yesterday evening) bzr Emacs > > and following your (Martin's) recipe by yanking it into a buffer and > > doing C-x C-e on it. > How do you configure your build? Can you show the exact configure and > make commands you use? ./configure --with-gif=no --with-tiff=no --with-gpm time make -j5 bootstrap . Normally, I run Emacs on a Linux tty, but I tried this build under X, too. This didn't make a difference. Somehow, I must have made some sort of version control mistake. There's no way that something so massive at the syntax.c level can be cheated by a crafty configure option. ;-( -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression. The purpose of revision 116070. 2014-01-26 9:54 ` Alan Mackenzie @ 2014-01-26 16:33 ` Eli Zaretskii 0 siblings, 0 replies; 93+ messages in thread From: Eli Zaretskii @ 2014-01-26 16:33 UTC (permalink / raw) To: Alan Mackenzie; +Cc: 16526 > Date: Sun, 26 Jan 2014 09:54:47 +0000 > Cc: rudalics@gmx.at, 16526@debbugs.gnu.org > From: Alan Mackenzie <acm@muc.de> > > > How do you configure your build? Can you show the exact configure and > > make commands you use? > > ./configure --with-gif=no --with-tiff=no --with-gpm > time make -j5 bootstrap Try this instead, and be amazed: CFLAGS='-O0 -g3' ./configure --with-gif=no --with-tiff=no --with-gpm --enable-checking='yes,glyphs' make -j5 IOW, force an unoptimized build, and add some diagnostics code to the display engine. My testing indicates that -O0 more than doubles the run time in this case, and --enable-checking doubles it some more -- for a total factor of 5 to 6. I get about 7 sec in an optimized version, and about 40 sec in the one configured as above. (In general, I believe that every Emacs developer who does something that can affect redisplay should always run an unoptimized build -- this will make any inefficiencies stand out very clearly.) See my other message with some results of digging into this problem; hopefully, you will be able to pick up where I left off. > There's no way that something so massive at the syntax.c level can > be cheated by a crafty configure option. ;-( Well, evidently it can. ^ permalink raw reply [flat|nested] 93+ messages in thread
* bug#16526: 24.3.50; scroll-conservatively & c-mode regression. The purpose of revision 116070. [not found] ` <20140125202721.GA3630@acm.acm> 2014-01-25 23:02 ` Stefan Monnier 2014-01-26 3:41 ` Eli Zaretskii @ 2014-01-26 17:35 ` Eli Zaretskii 2 siblings, 0 replies; 93+ messages in thread From: Eli Zaretskii @ 2014-01-26 17:35 UTC (permalink / raw) To: Alan Mackenzie; +Cc: 16526 > Date: Sat, 25 Jan 2014 20:27:21 +0000 > Cc: 16526@debbugs.gnu.org > From: Alan Mackenzie <acm@muc.de> > > If I've understood correctly, I think the root cause of the slowness is > the lack of optimisation of find_defun_start when open-paren-etc. is nil > - it brutally returns BOB, no matter what. FWIW, I don't think this is the culprit, at least not directly. Why does CC Mode fontification code decide to scan the buffer backwards from EOB, when point is at BOB, is a much more relevant question, so it seems. ^ permalink raw reply [flat|nested] 93+ messages in thread
end of thread, other threads:[~2014-07-07 7:07 UTC | newest] Thread overview: 93+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- [not found] <mailman.12613.1390467262.10748.bug-gnu-emacs@gnu.org> 2014-01-23 8:53 ` bug#16526: 24.3.50; scroll-conservatively & c-mode regression martin rudalics 2014-01-24 15:45 ` martin rudalics 2014-01-24 20:48 ` Alan Mackenzie [not found] ` <lbujij$1scv$1@colin.muc.de> 2014-01-25 3:50 ` Juanma Barranquero 2014-01-25 9:23 ` martin rudalics [not found] ` <52E38286.1050306@gmx.at> 2014-01-25 10:30 ` Eli Zaretskii 2014-01-25 14:58 ` martin rudalics [not found] ` <52E3D131.2090705@gmx.at> 2014-01-25 16:30 ` Eli Zaretskii 2014-01-25 16:48 ` martin rudalics 2014-01-25 17:29 ` Eli Zaretskii 2014-01-25 18:25 ` martin rudalics [not found] ` <52E4019C.5080905@gmx.at> 2014-01-25 18:31 ` Eli Zaretskii 2014-01-25 18:40 ` Eli Zaretskii 2014-01-26 11:20 ` martin rudalics [not found] ` <52E4EF61.3050404@gmx.at> 2014-01-26 17:20 ` Eli Zaretskii 2014-01-26 20:43 ` Alan Mackenzie 2014-01-27 8:21 ` martin rudalics 2014-01-29 21:52 ` Alan Mackenzie 2014-01-30 17:16 ` Eli Zaretskii 2014-01-31 20:00 ` Alan Mackenzie 2014-01-31 20:16 ` Eli Zaretskii [not found] ` <52E61704.6050807@gmx.at> 2014-01-27 14:49 ` Stefan Monnier [not found] ` <jwvvbx5fq2b.fsf-monnier+emacsbugs@gnu.org> 2014-01-27 17:25 ` martin rudalics [not found] ` <52E69695.5040703@gmx.at> 2014-01-28 0:16 ` Stefan Monnier 2014-01-29 22:36 ` Alan Mackenzie [not found] ` <20140129223626.GD3092@acm.acm> 2014-01-30 7:37 ` martin rudalics 2014-01-30 13:47 ` martin rudalics [not found] ` <52EA57D6.5080403@gmx.at> 2014-01-30 17:15 ` Eli Zaretskii 2014-01-30 18:58 ` martin rudalics [not found] ` <52EAA0C9.1090000@gmx.at> 2014-02-01 10:41 ` Eli Zaretskii 2014-02-02 13:18 ` martin rudalics 2014-02-02 17:40 ` Alan Mackenzie [not found] ` <20140202174050.GA5365@acm.acm> 2014-02-02 18:07 ` Eli Zaretskii 2014-02-02 19:20 ` Alan Mackenzie 2014-02-02 20:53 ` Eli Zaretskii 2014-02-05 23:00 ` Alan Mackenzie 2014-02-06 6:01 ` Eli Zaretskii 2014-06-22 16:49 ` Eli Zaretskii 2014-06-22 19:32 ` Alan Mackenzie 2014-06-22 20:04 ` Eli Zaretskii 2014-06-25 21:32 ` Alan Mackenzie 2014-06-26 2:51 ` Stefan Monnier 2014-06-27 20:34 ` Alan Mackenzie 2014-06-27 22:33 ` Stefan Monnier 2014-06-27 22:54 ` Stefan Monnier [not found] ` <jwv8uoim0bm.fsf-monnier+emacsbugs@gnu.org> 2014-06-28 13:00 ` Alan Mackenzie 2014-06-28 14:00 ` martin rudalics 2014-06-28 14:34 ` Stefan Monnier [not found] ` <53AECA88.7010401@gmx.at> 2014-06-28 14:55 ` Alan Mackenzie 2014-06-28 15:12 ` Eli Zaretskii 2014-06-28 16:30 ` Alan Mackenzie 2014-06-29 8:44 ` martin rudalics 2014-06-29 9:17 ` Alan Mackenzie 2014-06-29 10:06 ` martin rudalics [not found] ` <53AFE536.7010407@gmx.at> 2014-06-29 12:48 ` Alan Mackenzie 2014-06-29 14:18 ` martin rudalics 2014-06-29 14:41 ` Alan Mackenzie [not found] ` <20140629144151.GD2948@acm.acm> 2014-06-29 16:01 ` martin rudalics [not found] ` <53B03876.9070307@gmx.at> 2014-06-29 17:49 ` Alan Mackenzie 2014-06-30 7:55 ` martin rudalics 2014-06-30 13:48 ` Stefan Monnier [not found] ` <53B117D6.1050306@gmx.at> 2014-07-02 20:05 ` Alan Mackenzie [not found] ` <20140702200522.GB3823@acm.acm> 2014-07-03 1:57 ` Stefan Monnier 2014-07-03 8:40 ` martin rudalics [not found] ` <jwv61jf2owy.fsf-monnier+emacsbugs@gnu.org> 2014-07-03 14:59 ` Stefan Monnier 2014-07-04 18:27 ` Alan Mackenzie 2014-07-04 19:11 ` Stefan Monnier 2014-07-04 19:43 ` Stefan Monnier 2014-07-05 2:23 ` Stefan Monnier 2014-07-06 13:48 ` Alan Mackenzie 2014-07-07 1:52 ` Stefan Monnier 2014-07-07 7:07 ` martin rudalics [not found] ` <jwvsimevsvz.fsf-monnier+emacsbugs@gnu.org> 2014-07-07 7:07 ` martin rudalics 2014-07-05 20:25 ` Alan Mackenzie 2014-07-05 23:06 ` Stefan Monnier 2014-07-04 19:29 ` Alan Mackenzie 2014-07-05 1:52 ` Stefan Monnier 2014-07-05 7:47 ` Alan Mackenzie 2014-06-29 22:14 ` Stefan Monnier [not found] ` <jwvionjjrn7.fsf-monnier+emacsbugs@gnu.org> 2014-07-02 18:40 ` Alan Mackenzie [not found] ` <20140702184013.GA3823@acm.acm> 2014-07-02 19:40 ` Stefan Monnier [not found] ` <jwvsimpksv1.fsf-monnier+emacsbugs@gnu.org> 2014-06-28 17:33 ` Alan Mackenzie [not found] ` <20140628173334.GB2632@acm.acm> 2014-06-29 21:39 ` Stefan Monnier 2014-01-27 8:20 ` martin rudalics 2014-01-27 16:23 ` Eli Zaretskii 2014-01-27 17:26 ` martin rudalics 2014-01-26 11:19 ` martin rudalics 2014-01-25 20:27 ` bug#16526: 24.3.50; scroll-conservatively & c-mode regression. The purpose of revision 116070 Alan Mackenzie [not found] ` <20140125202721.GA3630@acm.acm> 2014-01-25 23:02 ` Stefan Monnier 2014-01-26 3:41 ` Eli Zaretskii 2014-01-26 9:54 ` Alan Mackenzie 2014-01-26 16:33 ` Eli Zaretskii 2014-01-26 17:35 ` Eli Zaretskii
Code repositories for project(s) associated with this public inbox https://git.savannah.gnu.org/cgit/emacs.git This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).