* bug#74357: c-mode: Some syntactic constructs cause unreasonable typing lag @ 2024-11-14 20:39 Björn Lindqvist 2024-11-15 7:40 ` Eli Zaretskii 0 siblings, 1 reply; 9+ messages in thread From: Björn Lindqvist @ 2024-11-14 20:39 UTC (permalink / raw) To: 74357 This bug has been present in c-mode for at least a year, but I haven't gotten around to report it. The reason is that bugs about latency are erratic and tricky to triage. Typing when the cursor is on some syntatic constructs in c-mode causes severe lag on the order of several hundred milliseconds on my (admittedly slow) laptop. The lag makes c-mode almost unusable. Here is an MWE: void foo(uint dc_dim, uint sc_dim, uint fy_dim, uint fx_dim, __global const float * restrict F, uint sy_dim, uint sx_dim, __global const float * restrict S, uint padding, __global float * restrict D) { uint dy_dim = sy_dim + 2 * padding - fy_dim + 1; uint dx_dim = sx_dim + 2 * padding - fx_dim + 1; // Place cursor at "y" in "dy_dim". Hold "y" and observe lag. uint dn = dc_dim * dy_dim * dx_dim; uint sn = sc_dim * sy_dim * sx_dim; } I can make typing even laggier by wrapping foo in foo, like this: void foo(...) { ... void foo(uint dc_dim, uint sc_dim, uint fy_dim, uint fx_dim, __global float * restrict F, uint sy_dim, uint sx_dim, __global float * restrict S, uint padding, __global float * restrict D) { uint dy_dim = sy_dim + 2 * padding - fy_dim + 1; uint dx_dim = sx_dim + 2 * padding - fx_dim + 1; // Place cursor at d[y]_dim. Hold "y". Observe lag in c-mode. uint dn = dc_dim * dy_dim * dx_dim; uint sn = sc_dim * sy_dim * sx_dim; } } The more times I wrap foo the slower c-mode gets. So if you have a fast computer try nesting foo in foo 50 times... I have observed the same annoying input lag on multiple computers and I don't use any special c-mode configuration. Please cc me as I'm not subscribed to the list. GNU Emacs 29.4 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.43, cairo version 1.18.2) -- mvh/best regards Björn Lindqvist ^ permalink raw reply [flat|nested] 9+ messages in thread
* bug#74357: c-mode: Some syntactic constructs cause unreasonable typing lag 2024-11-14 20:39 bug#74357: c-mode: Some syntactic constructs cause unreasonable typing lag Björn Lindqvist @ 2024-11-15 7:40 ` Eli Zaretskii 2024-11-15 14:08 ` Björn Lindqvist 0 siblings, 1 reply; 9+ messages in thread From: Eli Zaretskii @ 2024-11-15 7:40 UTC (permalink / raw) To: Björn Lindqvist, Alan Mackenzie; +Cc: 74357 > From: Björn Lindqvist <bjourne@gmail.com> > Date: Thu, 14 Nov 2024 21:39:53 +0100 > > This bug has been present in c-mode for at least a year, but I haven't > gotten around to report it. The reason is that bugs about latency are > erratic and tricky to triage. Typing when the cursor is on some > syntatic constructs in c-mode causes severe lag on the order of several > hundred milliseconds on my (admittedly slow) laptop. The lag > makes c-mode almost unusable. Here is an MWE: > > void foo(uint dc_dim, uint sc_dim, > uint fy_dim, uint fx_dim, > __global const float * restrict F, > uint sy_dim, uint sx_dim, > __global const float * restrict S, > uint padding, > __global float * restrict D) { > uint dy_dim = sy_dim + 2 * padding - fy_dim + 1; > uint dx_dim = sx_dim + 2 * padding - fx_dim + 1; > > // Place cursor at "y" in "dy_dim". Hold "y" and observe lag. > uint dn = dc_dim * dy_dim * dx_dim; > uint sn = sc_dim * sy_dim * sx_dim; > } > > I can make typing even laggier by wrapping foo in foo, like this: > > void foo(...) { > ... > void foo(uint dc_dim, uint sc_dim, > uint fy_dim, uint fx_dim, > __global float * restrict F, > uint sy_dim, uint sx_dim, > __global float * restrict S, > uint padding, > __global float * restrict D) { > uint dy_dim = sy_dim + 2 * padding - fy_dim + 1; > uint dx_dim = sx_dim + 2 * padding - fx_dim + 1; > > // Place cursor at d[y]_dim. Hold "y". Observe lag in c-mode. > uint dn = dc_dim * dy_dim * dx_dim; > uint sn = sc_dim * sy_dim * sx_dim; > } > } > > The more times I wrap foo the slower c-mode gets. So if you have a > fast computer try nesting foo in foo 50 times... I have observed the > same annoying input lag on multiple computers and I don't use any > special c-mode configuration. I've wrapped the snippet with 50 foo, and I still don't see any significant lags. Does it matter where you type, for reproducing the lag? Also, can you run this under a profiler (M-x profiler-start) and then show the full expanded profile produced by "M-x profiler-report" after several tens of seconds of typing with the lag? Adding Alan to the discussion. ^ permalink raw reply [flat|nested] 9+ messages in thread
* bug#74357: c-mode: Some syntactic constructs cause unreasonable typing lag 2024-11-15 7:40 ` Eli Zaretskii @ 2024-11-15 14:08 ` Björn Lindqvist 2024-11-15 14:25 ` Eli Zaretskii 0 siblings, 1 reply; 9+ messages in thread From: Björn Lindqvist @ 2024-11-15 14:08 UTC (permalink / raw) To: Eli Zaretskii; +Cc: Alan Mackenzie, 74357 > > From: Björn Lindqvist <bjourne@gmail.com> > > Date: Thu, 14 Nov 2024 21:39:53 +0100 > > > > This bug has been present in c-mode for at least a year, but I haven't > > gotten around to report it. The reason is that bugs about latency are > > erratic and tricky to triage. Typing when the cursor is on some > > syntatic constructs in c-mode causes severe lag on the order of several > > hundred milliseconds on my (admittedly slow) laptop. The lag > > makes c-mode almost unusable. Here is an MWE: > > > > void foo(uint dc_dim, uint sc_dim, > > uint fy_dim, uint fx_dim, > > __global const float * restrict F, > > uint sy_dim, uint sx_dim, > > __global const float * restrict S, > > uint padding, > > __global float * restrict D) { > > uint dy_dim = sy_dim + 2 * padding - fy_dim + 1; > > uint dx_dim = sx_dim + 2 * padding - fx_dim + 1; > > > > // Place cursor at "y" in "dy_dim". Hold "y" and observe lag. > > uint dn = dc_dim * dy_dim * dx_dim; > > uint sn = sc_dim * sy_dim * sx_dim; > > } > > > > I can make typing even laggier by wrapping foo in foo, like this: > > > > void foo(...) { > > ... > > void foo(uint dc_dim, uint sc_dim, > > uint fy_dim, uint fx_dim, > > __global float * restrict F, > > uint sy_dim, uint sx_dim, > > __global float * restrict S, > > uint padding, > > __global float * restrict D) { > > uint dy_dim = sy_dim + 2 * padding - fy_dim + 1; > > uint dx_dim = sx_dim + 2 * padding - fx_dim + 1; > > > > // Place cursor at d[y]_dim. Hold "y". Observe lag in c-mode. > > uint dn = dc_dim * dy_dim * dx_dim; > > uint sn = sc_dim * sy_dim * sx_dim; > > } > > } > > > > The more times I wrap foo the slower c-mode gets. So if you have a > > fast computer try nesting foo in foo 50 times... I have observed the > > same annoying input lag on multiple computers and I don't use any > > special c-mode configuration. > > I've wrapped the snippet with 50 foo, and I still don't see any > significant lags. > > Does it matter where you type, for reproducing the lag? > > Also, can you run this under a profiler (M-x profiler-start) and then > show the full expanded profile produced by "M-x profiler-report" after > several tens of seconds of typing with the lag? > > Adding Alan to the discussion. Hello Eli, thanks for the swift reply. I've created a much larger example so you can see what I mean with "wrapping foo in foo": https://gist.github.com/bjourne/8f705c5879aa966accf354008623f6bb Open file in c-mode, Go to line 328, place the cursor on "y" in "dy_dim" and press and hold "y". Unless you have a supercomputer the lag will be really apparent. Disable Global Font-lock mode and repeat the exercise. Lag will be gone. Lag is worse if I use non-jitted Emacs, but really apparent in jitted Emacs too. Lag goes away if I use c-ts-mode instead of c-mode. I want to emphasize that lag is present in normal code too, but easier to detect in these specially crafted samples. My system-configuration-features: "ACL CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS GPM GSETTINGS HARFBUZZ JPEG JSON LCMS2 LIBOTF LIBSYSTEMD LIBXML2 M17N_FLT MODULES NATIVE_COMP NOTIFY INOTIFY PDUMPER PNG RSVG SECCOMP SOUND SQLITE3 THREADS TIFF TOOLKIT_SCROLL_BARS TREE_SITTER WEBP X11 XDBE XIM XINPUT2 XPM GTK3 ZLIB" Profiler report: https://gist.github.com/bjourne/842695100e99c8fd6ef87fcdd0a6ed0b -- mvh/best regards Björn Lindqvist ^ permalink raw reply [flat|nested] 9+ messages in thread
* bug#74357: c-mode: Some syntactic constructs cause unreasonable typing lag 2024-11-15 14:08 ` Björn Lindqvist @ 2024-11-15 14:25 ` Eli Zaretskii 2024-11-15 14:45 ` Alan Mackenzie 2024-11-15 21:43 ` Björn Lindqvist 0 siblings, 2 replies; 9+ messages in thread From: Eli Zaretskii @ 2024-11-15 14:25 UTC (permalink / raw) To: Björn Lindqvist; +Cc: acm, 74357 > From: Björn Lindqvist <bjourne@gmail.com> > Date: Fri, 15 Nov 2024 15:08:09 +0100 > Cc: Alan Mackenzie <acm@muc.de>, 74357@debbugs.gnu.org > > > I've wrapped the snippet with 50 foo, and I still don't see any > > significant lags. > > > > Does it matter where you type, for reproducing the lag? > > > > Also, can you run this under a profiler (M-x profiler-start) and then > > show the full expanded profile produced by "M-x profiler-report" after > > several tens of seconds of typing with the lag? > > > > Adding Alan to the discussion. > > Hello Eli, thanks for the swift reply. > > > I've created a much larger example so you can see what I mean with > "wrapping foo in foo": > > https://gist.github.com/bjourne/8f705c5879aa966accf354008623f6bb > > Open file in c-mode, Go to line 328, place the cursor on "y" in "dy_dim" > and press and hold "y". Unless you have a supercomputer the lag will be > really apparent. Disable Global Font-lock mode and repeat the exercise. > Lag will be gone. Lag is worse if I use non-jitted Emacs, but really > apparent in jitted Emacs too. Lag goes away if I use c-ts-mode instead > of c-mode. Yes, I see the lag now, thanks; the profile is below. I'll let Alan look into this and see how this can be improved. > I want to emphasize that lag is present in normal code too, but easier > to detect in these specially crafted samples. Can you tell where in real life do you see such deeply-nested braces in C source files? Here's the profile I collected: 622 60% - redisplay_internal (C function) 615 59% - jit-lock-function 615 59% - jit-lock-fontify-now 614 59% - jit-lock--run-functions 614 59% - run-hook-wrapped 614 59% - #<byte-code-function 550> 614 59% - font-lock-fontify-region 614 59% - c-font-lock-fontify-region 582 56% - font-lock-default-fontify-region 581 56% - font-lock-fontify-keywords-region 323 31% - c-font-lock-cut-off-declarators 302 29% - c-get-fontification-context 301 29% - c-inside-bracelist-p 221 21% - c-looking-at-or-maybe-in-bracelist 154 14% - c-laomib-loop 69 6% - c-backward-sws 23 2% - c-beginning-of-macro 5 0% - back-to-indentation 2 0% skip-syntax-forward 1 0% line-end-position 1 0% backward-prefix-chars 4 0% beginning-of-line 3 0% looking-at 3 0% re-search-forward 2 0% line-end-position 2 0% match-data 1 0% #<byte-code-function 76C> 1 0% - #<byte-code-function 722> 1 0% set-match-data 1 0% make-closure 11 1% looking-at 7 0% skip-syntax-backward 5 0% - c-beginning-of-current-token 2 0% skip-syntax-backward 2 0% looking-at 5 0% forward-comment 3 0% skip-syntax-forward 1 0% make-closure 1 0% buffer-modified-p 50 4% - c-backward-token-2 41 3% - c-backward-sws 11 1% - c-beginning-of-macro 3 0% beginning-of-line 2 0% re-search-forward 2 0% - back-to-indentation 2 0% line-end-position 2 0% looking-at 1 0% - #<byte-code-function BFC> 1 0% set-match-data 7 0% looking-at 2 0% forward-comment 2 0% skip-syntax-backward 2 0% - c-beginning-of-current-token 2 0% skip-syntax-backward 1 0% buffer-modified-p 1 0% skip-syntax-forward 1 0% text-property-any 5 0% looking-at 1 0% scan-sexps 31 3% - c-at-macro-vsemi-p 13 1% looking-at 9 0% - c-backward-sws 7 0% looking-at 2 0% - c-beginning-of-current-token 1 0% looking-at 1 0% skip-syntax-backward 4 0% skip-syntax-backward 2 0% looking-at 53 5% - c-backward-token-2 49 4% scan-sexps 2 0% looking-at 1 0% - c-backward-sws 1 0% looking-at 12 1% - c-backward-sws 3 0% - c-beginning-of-macro 1 0% - back-to-indentation 1 0% skip-syntax-forward 1 0% looking-at 3 0% looking-at 1 0% forward-comment 1 0% skip-syntax-backward 1 0% skip-syntax-forward 1 0% c-laomib-get-cache 1 0% - c-back-over-compound-identifier 1 0% c-on-identifier 79 7% - c-looking-at-inexpr-block 38 3% scan-sexps 31 3% - c-backward-sws 12 1% - c-beginning-of-macro 2 0% - back-to-indentation 1 0% line-end-position 1 0% skip-syntax-forward 1 0% re-search-forward 1 0% make-closure 1 0% - #<byte-code-function 4CA> 1 0% set-match-data 1 0% looking-at 1 0% match-data 7 0% looking-at 3 0% skip-syntax-backward 2 0% - c-beginning-of-current-token 2 0% looking-at 2 0% forward-comment 10 0% looking-at 1 0% - c-backward-over-enum-header 1 0% scan-lists 1 0% - c-parse-state 1 0% - c-parse-state-1 1 0% - c-remove-stale-state-cache 1 0% - c-beginning-of-macro 1 0% re-search-forward 7 0% - c-determine-limit 4 0% parse-partial-sexp 3 0% - c-semi-pp-to-literal 3 0% parse-partial-sexp 6 0% - c-forward-decl-or-cast-1 3 0% - c-forward-type 2 0% - c-forward-name 2 0% - c-determine-+ve-limit 2 0% parse-partial-sexp 1 0% - c-forward-keyword-clause 1 0% - c-forward-sws 1 0% looking-at 1 0% scan-sexps 4 0% - c-font-lock-single-decl 4 0% - c-font-lock-declarators 4 0% - c-do-declarators 3 0% - c-forward-declarator 2 0% - c-forward-name 2 0% - c-determine-+ve-limit 2 0% parse-partial-sexp 1 0% - c-forward-decl-arglist 1 0% scan-lists 1 0% - c-syntactic-re-search-forward 1 0% re-search-forward 2 0% - c-back-over-member-initializers 1 0% - c-backward-sws 1 0% skip-syntax-backward 1 0% - c-parse-state 1 0% - c-parse-state-1 1 0% - c-remove-stale-state-cache 1 0% - c-beginning-of-macro 1 0% looking-at 2 0% - c-at-toplevel-p 1 0% - c-search-uplist-for-classkey 1 0% - c-looking-at-decl-block 1 0% scan-lists 1 0% - c-parse-state 1 0% - c-parse-state-1 1 0% c-append-to-state-cache 226 21% - c-font-lock-declarations 226 21% - c-find-decl-spots 221 21% - #<byte-code-function 228> 170 16% - c-get-fontification-context 166 16% - c-inside-bracelist-p 108 10% - c-looking-at-or-maybe-in-bracelist 69 6% - c-laomib-loop 41 3% - c-backward-sws 11 1% looking-at 8 0% forward-comment 6 0% - c-beginning-of-macro 1 0% beginning-of-line 1 0% - back-to-indentation 1 0% line-end-position 1 0% re-search-forward 3 0% - c-beginning-of-current-token 2 0% skip-syntax-backward 1 0% looking-at 2 0% skip-syntax-backward 2 0% skip-syntax-forward 1 0% text-property-any 21 2% - c-backward-token-2 16 1% - c-backward-sws 4 0% - c-beginning-of-macro 2 0% - back-to-indentation 1 0% line-end-position 1 0% skip-syntax-forward 1 0% re-search-forward 1 0% - #<byte-code-function 75C> 1 0% set-match-data 3 0% skip-syntax-backward 2 0% looking-at 1 0% - c-beginning-of-current-token 1 0% looking-at 2 0% scan-sexps 6 0% - c-at-macro-vsemi-p 3 0% - c-backward-sws 2 0% looking-at 1 0% - c-beginning-of-current-token 1 0% looking-at 2 0% looking-at 1 0% looking-at 29 2% - c-backward-token-2 26 2% scan-sexps 2 0% looking-at 1 0% - c-backward-sws 1 0% looking-at 8 0% - c-backward-sws 3 0% skip-syntax-backward 2 0% looking-at 1 0% forward-comment 1 0% - c-beginning-of-macro 1 0% match-data 1 0% c-laomib-get-cache 55 5% - c-looking-at-inexpr-block 30 2% scan-sexps 16 1% - c-backward-sws 6 0% - c-beginning-of-macro 2 0% match-data 1 0% - back-to-indentation 1 0% line-end-position 1 0% beginning-of-line 5 0% looking-at 1 0% - c-beginning-of-current-token 1 0% skip-syntax-backward 1 0% skip-syntax-backward 1 0% #<byte-code-function FF6> 7 0% looking-at 2 0% - c-backward-over-enum-header 2 0% scan-lists 3 0% - c-parse-state 2 0% - c-parse-state-1 2 0% - c-remove-stale-state-cache 2 0% - c-beginning-of-macro 2 0% - back-to-indentation 2 0% backward-prefix-chars 1 0% - c-beginning-of-macro 1 0% - back-to-indentation 1 0% backward-prefix-chars 43 4% - c-forward-decl-or-cast-1 35 3% - c-forward-type 21 2% - c-forward-name 18 1% - c-determine-+ve-limit 16 1% parse-partial-sexp 1 0% skip-syntax-backward 1 0% looking-at 5 0% looking-at 5 0% - c-forward-sws 3 0% looking-at 2 0% - c-check-qualified-type 2 0% - c-forward-over-compound-identifier 2 0% - c-forward-over-token 2 0% - c-forward-sws 2 0% looking-at 1 0% - c-add-type 1 0% - c-add-type-1 1 0% - c-syntactic-content 1 0% re-search-forward 5 0% - c-forward-name 5 0% - c-determine-+ve-limit 5 0% parse-partial-sexp 3 0% looking-at 6 0% - c-font-lock-single-decl 6 0% - c-font-lock-declarators 6 0% - c-do-declarators 6 0% - c-forward-declarator 3 0% - c-forward-name 1 0% - c-determine-+ve-limit 1 0% parse-partial-sexp 1 0% - c-forward-sws 1 0% looking-at 1 0% looking-at 2 0% c-syntactic-re-search-forward 1 0% looking-at 1 0% looking-at 1 0% - c-backward-sws 1 0% text-property-any 5 0% - c-bs-at-toplevel-p 5 0% - c-brace-stack-at 5 0% - c-update-brace-stack 5 0% - c-syntactic-re-search-forward 3 0% parse-partial-sexp 2 0% - c-beginning-of-macro 1 0% make-closure 1 0% - back-to-indentation 1 0% beginning-of-line 27 2% - c-font-lock-enclosing-decls 12 1% - c-syntactic-skip-backward 5 0% - c-beginning-of-macro 3 0% - back-to-indentation 2 0% line-end-position 1 0% backward-prefix-chars 1 0% looking-at 1 0% line-end-position 4 0% - c-literal-start 4 0% - c-semi-pp-to-literal 4 0% parse-partial-sexp 2 0% - c-backward-sws 2 0% skip-syntax-backward 7 0% - c-forward-sws 6 0% looking-at 5 0% - c-determine-limit 5 0% parse-partial-sexp 2 0% looking-at 1 0% - c-parse-state 1 0% - c-parse-state-1 1 0% - c-append-to-state-cache 1 0% scan-lists 3 0% - c-font-lock-enum-tail 2 0% - c-parse-state 2 0% - c-parse-state-1 2 0% - c-append-to-state-cache 1 0% - c-beginning-of-macro 1 0% - #<byte-code-function 2B4> 1 0% set-match-data 1 0% scan-lists 1 0% - c-backward-over-enum-header 1 0% scan-lists 2 0% - c-font-lock-complex-decl-prepare 2 0% c-backward-sws 1 0% - font-lock-fontify-syntactically-region 1 0% - font-lock-default-fontify-syntactically 1 0% - syntax-ppss 1 0% parse-partial-sexp 32 3% - c-before-context-fl-expand-region 32 3% - mapc 32 3% - #<byte-code-function 364> 32 3% - c-context-expand-fl-region 16 1% - c-fl-decl-end 13 1% - c-determine-limit 11 1% - c-semi-pp-to-literal 10 0% parse-partial-sexp 1 0% looking-at 1 0% parse-partial-sexp 1 0% - c-determine-limit-no-macro 1 0% - c-beginning-of-macro 1 0% beginning-of-line 2 0% - c-forward-declarator 1 0% - c-forward-name 1 0% - c-determine-+ve-limit 1 0% parse-partial-sexp 1 0% - c-syntactic-re-search-forward 1 0% - c-beginning-of-macro 1 0% beginning-of-line 1 0% - c-backward-sws 1 0% - c-beginning-of-current-token 1 0% looking-at 16 1% - c-fl-decl-start 5 0% - c-forward-type 4 0% - c-forward-name 2 0% - c-determine-+ve-limit 2 0% parse-partial-sexp 1 0% looking-at 1 0% - c-forward-sws 1 0% looking-at 1 0% looking-at 4 0% - c-determine-limit 4 0% parse-partial-sexp 2 0% - c-syntactic-skip-backward 1 0% - c-literal-start 1 0% - c-semi-pp-to-literal 1 0% parse-partial-sexp 1 0% - c-beginning-of-macro 1 0% - back-to-indentation 1 0% line-end-position 2 0% - c-looking-at-or-maybe-in-bracelist 2 0% - c-backward-token-2 2 0% scan-sexps 2 0% - c-literal-start 2 0% - c-semi-pp-to-literal 2 0% parse-partial-sexp 1 0% - c-parse-state 1 0% - c-parse-state-1 1 0% - c-remove-stale-state-cache-backwards 1 0% - c-state-literal-at 1 0% - c-state-pp-to-literal 1 0% parse-partial-sexp 387 37% Automatic GC 13 1% - command-execute 13 1% - call-interactively 10 0% - funcall-interactively 5 0% - self-insert-command 3 0% - c-after-change 3 0% - mapc 3 0% - #<byte-code-function B02> 3 0% - c-change-expand-fl-region 3 0% - c-fl-decl-end 1 0% c-backward-sws 1 0% - c-forward-declarator 1 0% - c-forward-name 1 0% - c-forward-sws 1 0% looking-at 2 0% - c-before-change 1 0% - c-determine-limit 1 0% parse-partial-sexp 1 0% - c-invalidate-sws-region-before 1 0% - c-literal-limits 1 0% c-full-pp-to-literal 5 0% - next-line 5 0% - line-move 5 0% - line-move-partial 5 0% - pos-visible-in-window-p 4 0% - jit-lock-function 4 0% - jit-lock-fontify-now 4 0% - jit-lock--run-functions 4 0% - run-hook-wrapped 4 0% - #<byte-code-function 9C0> 4 0% - font-lock-fontify-region 4 0% - c-font-lock-fontify-region 3 0% - font-lock-default-fontify-region 3 0% - font-lock-fontify-keywords-region 2 0% - c-font-lock-cut-off-declarators 2 0% - c-get-fontification-context 2 0% - c-inside-bracelist-p 1 0% - c-looking-at-or-maybe-in-bracelist 1 0% c-laomib-loop 1 0% - c-looking-at-inexpr-block 1 0% scan-sexps 1 0% - c-font-lock-declarations 1 0% - c-find-decl-spots 1 0% - #<byte-code-function DC4> 1 0% - c-forward-decl-or-cast-1 1 0% looking-at 1 0% - c-before-context-fl-expand-region 1 0% - mapc 1 0% - #<byte-code-function E22> 1 0% - c-context-expand-fl-region 1 0% - c-fl-decl-end 1 0% - c-determine-limit 1 0% - c-semi-pp-to-literal 1 0% parse-partial-sexp 3 0% - byte-code 3 0% - read-extended-command 3 0% - read-extended-command-1 3 0% - completing-read 3 0% - completing-read-default 3 0% - read-from-minibuffer 1 0% redisplay_internal (C function) 7 0% - timer-event-handler 7 0% - apply 6 0% - c-force-redisplay 6 0% - c-font-lock-fontify-region 5 0% - font-lock-default-fontify-region 4 0% - font-lock-fontify-keywords-region 2 0% - c-font-lock-declarations 2 0% - c-find-decl-spots 2 0% - c-bs-at-toplevel-p 2 0% - c-brace-stack-at 2 0% - c-update-brace-stack 2 0% - c-syntactic-re-search-forward 2 0% parse-partial-sexp 1 0% - c-font-lock-enclosing-decls 1 0% - c-syntactic-skip-backward 1 0% - c-literal-start 1 0% - c-semi-pp-to-literal 1 0% parse-partial-sexp 1 0% re-search-forward 1 0% - font-lock-fontify-syntactically-region 1 0% - font-lock-default-fontify-syntactically 1 0% - syntax-ppss 1 0% parse-partial-sexp 1 0% - c-before-context-fl-expand-region 1 0% - mapc 1 0% - #<byte-code-function FA0> 1 0% - c-context-expand-fl-region 1 0% - c-fl-decl-end 1 0% - c-determine-limit 1 0% - c-semi-pp-to-literal 1 0% parse-partial-sexp 1 0% - #<byte-code-function 88A> 1 0% - completion--in-region-1 1 0% - completion--do-completion 1 0% - completion-try-completion 1 0% - completion--nth-completion 1 0% - seq-some 1 0% - seq-do 1 0% - mapc 1 0% - #<byte-code-function 35C> 1 0% - #<byte-code-function 008> 1 0% - completion-basic-try-completion 1 0% - try-completion 1 0% - #<byte-code-function 704> 1 0% - complete-with-action 1 0% try-completion 0 0% ... ^ permalink raw reply [flat|nested] 9+ messages in thread
* bug#74357: c-mode: Some syntactic constructs cause unreasonable typing lag 2024-11-15 14:25 ` Eli Zaretskii @ 2024-11-15 14:45 ` Alan Mackenzie 2024-11-15 21:43 ` Björn Lindqvist 1 sibling, 0 replies; 9+ messages in thread From: Alan Mackenzie @ 2024-11-15 14:45 UTC (permalink / raw) To: Eli Zaretskii; +Cc: acm, Björn Lindqvist, 74357 Hello, Eli and Björn. On Fri, Nov 15, 2024 at 16:25:39 +0200, Eli Zaretskii wrote: > > From: Björn Lindqvist <bjourne@gmail.com> > > Date: Fri, 15 Nov 2024 15:08:09 +0100 > > Cc: Alan Mackenzie <acm@muc.de>, 74357@debbugs.gnu.org > > > I've wrapped the snippet with 50 foo, and I still don't see any > > > significant lags. > > > Does it matter where you type, for reproducing the lag? > > > Also, can you run this under a profiler (M-x profiler-start) and then > > > show the full expanded profile produced by "M-x profiler-report" after > > > several tens of seconds of typing with the lag? > > > Adding Alan to the discussion. > > Hello Eli, thanks for the swift reply. > > I've created a much larger example so you can see what I mean with > > "wrapping foo in foo": > > https://gist.github.com/bjourne/8f705c5879aa966accf354008623f6bb > > Open file in c-mode, Go to line 328, place the cursor on "y" in "dy_dim" > > and press and hold "y". Unless you have a supercomputer the lag will be > > really apparent. Disable Global Font-lock mode and repeat the exercise. > > Lag will be gone. Lag is worse if I use non-jitted Emacs, but really > > apparent in jitted Emacs too. Lag goes away if I use c-ts-mode instead > > of c-mode. > Yes, I see the lag now, thanks; the profile is below. I'll let Alan > look into this and see how this can be improved. Thanks, Eli! I'll look into this. > > I want to emphasize that lag is present in normal code too, but easier > > to detect in these specially crafted samples. > Can you tell where in real life do you see such deeply-nested braces > in C source files? > Here's the profile I collected: [ .... ] -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 9+ messages in thread
* bug#74357: c-mode: Some syntactic constructs cause unreasonable typing lag 2024-11-15 14:25 ` Eli Zaretskii 2024-11-15 14:45 ` Alan Mackenzie @ 2024-11-15 21:43 ` Björn Lindqvist 2024-11-16 11:00 ` Eli Zaretskii 2024-11-28 20:03 ` Alan Mackenzie 1 sibling, 2 replies; 9+ messages in thread From: Björn Lindqvist @ 2024-11-15 21:43 UTC (permalink / raw) To: Eli Zaretskii; +Cc: acm, 74357 Den fre 15 nov. 2024 kl 15:25 skrev Eli Zaretskii <eliz@gnu.org>: > Can you tell where in real life do you see such deeply-nested braces > in C source files? 50 is perhaps exaggerating it, but in "modern" C++ with multiple namespaces, nested classes, and anonymous functions you can easily get scopes nested over a dozen levels deep. -- mvh/best regards Björn Lindqvist ^ permalink raw reply [flat|nested] 9+ messages in thread
* bug#74357: c-mode: Some syntactic constructs cause unreasonable typing lag 2024-11-15 21:43 ` Björn Lindqvist @ 2024-11-16 11:00 ` Eli Zaretskii 2024-11-28 20:03 ` Alan Mackenzie 1 sibling, 0 replies; 9+ messages in thread From: Eli Zaretskii @ 2024-11-16 11:00 UTC (permalink / raw) To: Björn Lindqvist; +Cc: acm, 74357 > From: Björn Lindqvist <bjourne@gmail.com> > Date: Fri, 15 Nov 2024 22:43:45 +0100 > Cc: acm@muc.de, 74357@debbugs.gnu.org > > Den fre 15 nov. 2024 kl 15:25 skrev Eli Zaretskii <eliz@gnu.org>: > > Can you tell where in real life do you see such deeply-nested braces > > in C source files? > > 50 is perhaps exaggerating it, but in "modern" C++ with multiple > namespaces, nested classes, and anonymous functions you can easily get > scopes nested over a dozen levels deep. Can you show such a file from a real-life project? I'd like us to have it as a means for judging real-life performance in these cases. Thanks. ^ permalink raw reply [flat|nested] 9+ messages in thread
* bug#74357: c-mode: Some syntactic constructs cause unreasonable typing lag 2024-11-15 21:43 ` Björn Lindqvist 2024-11-16 11:00 ` Eli Zaretskii @ 2024-11-28 20:03 ` Alan Mackenzie 2024-11-29 23:18 ` Alan Mackenzie 1 sibling, 1 reply; 9+ messages in thread From: Alan Mackenzie @ 2024-11-28 20:03 UTC (permalink / raw) To: Björn Lindqvist; +Cc: acm, Eli Zaretskii, 74357 Hello, Björn. On Fri, Nov 15, 2024 at 22:43:45 +0100, Björn Lindqvist wrote: > Den fre 15 nov. 2024 kl 15:25 skrev Eli Zaretskii <eliz@gnu.org>: > > Can you tell where in real life do you see such deeply-nested braces > > in C source files? > 50 is perhaps exaggerating it, but in "modern" C++ with multiple > namespaces, nested classes, and anonymous functions you can easily get > scopes nested over a dozen levels deep. In your test file, near the end, holding down the 'y' key as you describe, most of the time CC Mode is scanning for brace lists (and not finding them). ("Brace lists" are things like the initialisation forms for structs and arrays, not statement blocks.) There is a cache mechanism to help reduce this scanning, but with the deep nesting in the test file, it seems to be ineffective, with elements of that cache continually being overwritten by new elements. The cache currently has just four elements. Maybe it would be better to increase that number. Maybe there's some other problem with the cache. I'm looking into it. > -- > mvh/best regards Björn Lindqvist -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 9+ messages in thread
* bug#74357: c-mode: Some syntactic constructs cause unreasonable typing lag 2024-11-28 20:03 ` Alan Mackenzie @ 2024-11-29 23:18 ` Alan Mackenzie 0 siblings, 0 replies; 9+ messages in thread From: Alan Mackenzie @ 2024-11-29 23:18 UTC (permalink / raw) To: Björn Lindqvist; +Cc: acm, Eli Zaretskii, 74357 Hello again, Björn. On Thu, Nov 28, 2024 at 20:03:33 +0000, Alan Mackenzie wrote: > On Fri, Nov 15, 2024 at 22:43:45 +0100, Björn Lindqvist wrote: > > Den fre 15 nov. 2024 kl 15:25 skrev Eli Zaretskii <eliz@gnu.org>: > > > Can you tell where in real life do you see such deeply-nested braces > > > in C source files? > > 50 is perhaps exaggerating it, but in "modern" C++ with multiple > > namespaces, nested classes, and anonymous functions you can easily get > > scopes nested over a dozen levels deep. > In your test file, near the end, holding down the 'y' key as you > describe, most of the time CC Mode is scanning for brace lists (and not > finding them). ("Brace lists" are things like the initialisation forms > for structs and arrays, not statement blocks.) > There is a cache mechanism to help reduce this scanning, but with the > deep nesting in the test file, it seems to be ineffective, with elements > of that cache continually being overwritten by new elements. The cache > currently has just four elements. Maybe it would be better to increase > that number. Maybe there's some other problem with the cache. I'm > looking into it. It turns out that that cache mechanism was almost totally ineffective. I've put a new cache into c-inside-bracelist-p. More precisely, I've reused an existing cache in a new way. Would you please apply the patch below to your CC Mode, byte compile CC Mode, and test it a bit to see if it's fast enough. (If you want any help applying the patch or byte compiling the result, feel free to send me private email.) Thanks! diff -r 2c1ba136f3f2 cc-engine.el --- a/cc-engine.el Mon Oct 28 15:47:50 2024 +0000 +++ b/cc-engine.el Fri Nov 29 23:12:27 2024 +0000 @@ -13178,7 +13178,7 @@ (setq c-laomib-cache (delq elt c-laomib-cache))))))) (defun c-looking-at-or-maybe-in-bracelist (&optional containing-sexp lim) - ;; Point is at an open brace. If this starts a brace list, return a list + ;; Point is at an open brace. If this starts a brace list, return a cons ;; whose car is the buffer position of the start of the construct which ;; introduces the list, and whose cdr is the symbol `in-paren' if the brace ;; is directly enclosed in a parenthesis form (i.e. an arglist), t if we @@ -13411,14 +13411,19 @@ (t t)))) ;; The caller can go up one level. )))) +;; A list of the form returned by `c-parse-state'. Each opening brace in it +;; is not the brace of a brace list. +(defvar c-no-bracelist-cache nil) +(make-variable-buffer-local 'c-no-bracelist-cache) + (defun c-inside-bracelist-p (containing-sexp paren-state accept-in-paren) - ;; return the buffer position of the beginning of the brace list statement + ;; Return the buffer position of the beginning of the brace list statement ;; if CONTAINING-SEXP is inside a brace list, otherwise return nil. ;; - ;; CONTAINING-SEXP is the buffer pos of the innermost containing paren. NO - ;; IT ISN'T!!! [This function is badly designed, and probably needs - ;; reformulating without its first argument, and the critical position being - ;; at point.] + ;; CONTAINING-SEXP must be at an open brace, and is the buffer pos of the + ;; innermost containing brace. NO IT ISN'T!!! [This function is badly + ;; designed, and probably needs reformulating without its first argument, + ;; and the critical position being at point.] ;; ;; PAREN-STATE is the remainder of the state of enclosing braces. ;; ACCEPT-IN-PAREN is non-nil iff we will accept as a brace list a brace @@ -13432,32 +13437,42 @@ ;; speed. ;; ;; This function might do hidden buffer changes. - ;; this will pick up array/aggregate init lists, even if they are nested. - (save-excursion - (let ((bufpos t) - next-containing) - (while (and (eq bufpos t) - containing-sexp) - (when paren-state - (setq next-containing (c-pull-open-brace paren-state))) - - (goto-char containing-sexp) - (if (c-looking-at-inexpr-block next-containing next-containing) - ;; We're in an in-expression block of some kind. Do not - ;; check nesting. We deliberately set the limit to the - ;; containing sexp, so that c-looking-at-inexpr-block - ;; doesn't check for an identifier before it. - (setq bufpos nil) - (if (not (eq (char-after) ?{)) - (setq bufpos nil) - (when (eq (setq bufpos (c-looking-at-or-maybe-in-bracelist - next-containing next-containing)) - t) - (setq containing-sexp next-containing - next-containing nil))))) - (and (consp bufpos) - (or accept-in-paren (not (eq (cdr bufpos) 'in-paren))) - (car bufpos))))) + ;; It will pick up array/aggregate init lists, even if they are nested. + (save-excursion + (let ((bufpos t) + next-containing + (whole-paren-state (cons containing-sexp paren-state)) + (current-brace containing-sexp)) + (while (and (eq bufpos t) + current-brace + (not (memq current-brace c-no-bracelist-cache))) + (when paren-state + (setq next-containing (c-pull-open-brace paren-state))) + + (goto-char current-brace) + (cond + ((c-looking-at-inexpr-block next-containing next-containing) + ;; We're in an in-expression block of some kind. Do not + ;; check nesting. We deliberately set the limit to the + ;; containing sexp, so that c-looking-at-inexpr-block + ;; doesn't check for an identifier before it. + (setq bufpos nil)) + ((not (eq (char-after) ?{)) + (setq bufpos nil)) + ((eq (setq bufpos (c-looking-at-or-maybe-in-bracelist + next-containing next-containing)) + t) + (setq current-brace + next-containing + next-containing nil)))) + (cond + ((and (consp bufpos) + (or accept-in-paren (not (eq (cdr bufpos) 'in-paren)))) + (car bufpos)) + ((not (memq containing-sexp c-no-bracelist-cache)) + ;; Update `c-no-bracelist-cache' + (setq c-no-bracelist-cache (copy-tree whole-paren-state)) + nil))))) (defun c-looking-at-special-brace-list () ;; If we're looking at the start of a pike-style list, i.e., `({ })', diff -r 2c1ba136f3f2 cc-mode.el --- a/cc-mode.el Mon Oct 28 15:47:50 2024 +0000 +++ b/cc-mode.el Fri Nov 29 23:12:27 2024 +0000 @@ -2313,7 +2313,9 @@ ;; The following must happen after the previous, which likely alters ;; the macro cache. (when c-opt-cpp-symbol - (c-invalidate-macro-cache beg end))))) + (c-invalidate-macro-cache beg end)) + (setq c-no-bracelist-cache + (c-whack-state-after beg c-no-bracelist-cache))))) (defvar c-in-after-change-fontification nil) (make-variable-buffer-local 'c-in-after-change-fontification) > > -- > > mvh/best regards Björn Lindqvist -- Alan Mackenzie (Nuremberg, Germany). ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2024-11-29 23:18 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2024-11-14 20:39 bug#74357: c-mode: Some syntactic constructs cause unreasonable typing lag Björn Lindqvist 2024-11-15 7:40 ` Eli Zaretskii 2024-11-15 14:08 ` Björn Lindqvist 2024-11-15 14:25 ` Eli Zaretskii 2024-11-15 14:45 ` Alan Mackenzie 2024-11-15 21:43 ` Björn Lindqvist 2024-11-16 11:00 ` Eli Zaretskii 2024-11-28 20:03 ` Alan Mackenzie 2024-11-29 23:18 ` Alan Mackenzie
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).