Closed martinjlowm closed 4 years ago
Emacs (unfortunately) has a long history of terrible performance with long lines.
You may be able to replicate the same behaviour in a fundamental-mode buffer, but I honestly won’t be surprised if it’s worse with csharp-mode active.
How long lines are we talking about here?
I noticed it from a base64-encoded (non-wrapped) string of just under 10k characters.
Yeah. That will probably kill any Emacs-mode, not just csharp-mode.
That has to be fixed in core Emacs.
10k characters is basically nothing in this scenario. To compare, c-mode
starts to slow down slightly at 100k (non-wrapping) lines.
C# had much more complex grammar than basic C has. Thus the (all elisp) parser is more involved too.
This has a cost, especially noticeable wrt speed of fortification, and particularly so for long lines.
You may consider “so long” a viable work-around for such cases:
SoLong is definitely a good tip. I didn't know of that package! Thank you :)
For reference, check out the following (30s split and sped up) GIFs comparing csharp-mode
, c-mode
and javascript-mode
(in order) which all use cc-mode (if I'm not mistaken):
1/4
2/4
3/4 (too big for embedding) https://i.imgur.com/uEvD3Gf
4/4
If you want to get involved and profiling and analyzing where csharp-mode is slowing down relative to the other modes, I’m all ears.
If that results in a PR I will be first in line to review!
Unfortunately right now I don’t have time or motivation to go with those initiatives myself.
Are you willing to take a look?
I might. :)
If I find some time, I'll take a look at it.
A quick memory profile reveals the culprit:
- redisplay_internal (C function) 3,130,139,663 99%
- jit-lock-function 3,117,177,995 98%
- jit-lock-fontify-now 3,117,172,715 98%
- jit-lock--run-functions 3,117,156,171 98%
- run-hook-wrapped 3,117,156,171 98%
- #<compiled 0x452818e1> 3,117,156,171 98%
- font-lock-fontify-region 3,117,156,171 98%
- c-font-lock-fontify-region 3,117,135,051 98%
- font-lock-default-fontify-region 3,117,135,051 98%
- font-lock-fontify-keywords-region 3,116,713,974 98%
c-font-lock-<>-arglists 3,104,775,374 98% <--
- c-font-lock-declarations 5,346,092 0%
+ c-find-decl-spots 5,341,868 0%
+ c-font-lock-cut-off-declarators 1,432,360 0%
+ #<compiled 0x44abe6fd> 634,538 0%
+ c-font-lock-complex-decl-prepare 491,510 0%
#<compiled 0x44c4f6f1> 266,516 0%
+ #<lambda 0x8b497ab0f80> 241,388 0%
#<compiled 0x41771d45> 241,378 0%
#<compiled 0x44edd3b1> 222,192 0%
#<compiled 0x44abf481> 214,788 0%
#<compiled 0x44af1991> 208,878 0%
#<compiled 0x40fcdf29> 208,364 0%
#<compiled 0x44ab8229> 198,754 0%
#<compiled 0x41735be9> 197,628 0%
#<compiled 0x44abc6fd> 190,428 0%
+ c-font-lock-enclosing-decls 159,052 0%
+ font-lock-fontify-syntactically-region 421,077 0%
+ eval 12,961,668 0%
- command-execute 30,893,785 0%
- call-interactively 30,893,785 0%
- funcall-interactively 30,893,785 0%
+ kill-ring-save 18,350,712 0%
+ counsel-M-x 7,388,634 0%
+ yank 4,725,637 0%
+ self-insert-command 424,054 0%
+ left-word 2,080 0%
+ set-mark-command 242 0%
internal-echo-keystrokes-prefix 49,632 0%
- flycheck-display-error-at-point-soon 14,696 0%
- flycheck-overlays-at 14,696 0%
- flycheck-filter-overlays 14,536 0%
seq-filter 14,536 0%
eshell-output-filter 12,592 0%
+ timer-event-handler 11,404 0%
... 0 0%
Removing c-recognize-<>-arglists
and making csharp-mode
base off of c-mode
instead, things start to become snappy:
1 file changed, 3 insertions(+), 3 deletions(-)
csharp-mode.el | 6 +++---
modified csharp-mode.el
@@ -449,7 +449,7 @@ Most other csharp functions are not instrumented.
;; mode as the fallback for the constants we don't change here.
;; This needs to be done also at compile time since the language
;; constants are evaluated then.
- (c-add-language 'csharp-mode 'java-mode))
+ (c-add-language 'csharp-mode 'c-mode))
;; ==================================================================
;; end of c# upfront stuff
@@ -1184,8 +1184,8 @@ Currently handled:
;; C# does generics. Setting this to t tells the parser to put
;; parenthesis syntax on angle braces that surround a comma-separated
;; list.
-(c-lang-defconst c-recognize-<>-arglists
- csharp t)
+;; (c-lang-defconst c-recognize-<>-arglists
+;; csharp t)
(c-lang-defconst c-identifier-key
[back]
Obviously, this is not a solution and it affects java-mode
as well - my search continues...
A quick memory profile reveals the culprit
Nice. Care to share how you did that? :)
Obviously, this is not a solution and it affects java-mode as well - my search continues
It's clearly not a solution, but just for fun, I decided to run make test
:
Ran 29 tests, 28 results as expected, 1 unexpected (2019-05-16 11:21:05+0200, 0.905807 sec)
That's a whole lot better than I expected :laughing:
M-x profiler-start
, do your thing and then run M-x profiler-report
. It was new to me as well :P
@martinjlowm @josteink
Emacs 27.1 will arrive with this long-awaited fix:
https://github.com/emacs-mirror/emacs/commit/4ac905f88f10439ca0795b217a046e3a62895fc4
I don't have anymore this slowness in long JSON and minified JS files :D
more information: https://www.reddit.com/r/emacs/comments/ccoksw/solong_mitigating_slowness_due_to_extremely_long/
That's great news, @lxbarbosa !
Since the fix is in Emacs itself and not in csharp-mode
, I'll close this issue for now. Hope that's OK with everyone.
Something as simple as
makes Emacs unresponsive (probably indentation related) - not even C-g cancels whatever is going on. The amount of time Emacs hangs increases with the length of abc.
This happens on Emacs 26.1 (OS X 10.12.6) with
--no-init-file
andcsharp-mode
(csharp-mode-20181011.718) enabled.