brrd / abricotine

Markdown editor with inline preview
GNU General Public License v3.0
2.63k stars 159 forks source link

Performance issues on scroll #274

Closed brrd closed 4 years ago

brrd commented 4 years ago

The editor encounters huge performance issues on scroll, obviously because of this event handler:

https://github.com/brrd/Abricotine/blob/63de38d54eb30d6f893f045dc698423397917556/app/renderer/cm-init.js#L160-L171

On a ~100 lines document, this function takes more than 250ms to run, which freezes the editor each time CodeMirror "updates". This results in a jerky scrolling.

image

Parsing threw the whole document line by line with cm.eachLine and running getModeAt (which is very expensive) each time is a very bad design which should be avoided. Instead, empty lines in code blocks should be styled by using the markdown parser as expected.

nathanlesage commented 4 years ago

Just checked back on your awesome editor to see how it's going and immediately found this issue!

Concerning this:

On a ~100 lines document, this function takes more than 250ms to run, which freezes the editor each time CodeMirror "updates". This results in a jerky scrolling.

Yes, if you always perform that function it can be burdensome. What I found out is that what best works is to fire some events only during CodeMirror.on('cursorActivity'): https://github.com/Zettlr/Zettlr/blob/develop/source/renderer/zettlr-editor.js#L358

Here's how I recently implemented the background colors on codeblocks: https://github.com/Zettlr/Zettlr/blob/develop/source/renderer/assets/codemirror/zettlr-plugin-markdown-codeblock-classes.js

Not on update but on cursorActivity, because in fact the line classes are cached by CodeMirror and are applied automatically, you only need to (re)set them when the code actually changes! (P.S.: I'm completely unsure whether or not the operation helps or is just decoration …)

brrd commented 4 years ago

Just checked back on your awesome editor to see how it's going and immediately found this issue!

🙏 Thank you very much @nathanlesage. By the way I have to say that I find your work with Zettlr truly amazing.

Your advice is very helpful, I will definitely have a closer look at it.

You may also be interested in this solution, which I found in HyperMD: https://github.com/laobubu/HyperMD/blob/7bdeb397ba56d944c9290fbda8a32869e7cc3dfb/src/mode/hypermd.ts

This relies on a rewriting of CodeMirror markdown mode. This way, codeblock classes are added directly with the parser, which is IMO the most performant solution (but also the most difficult to implement).

nathanlesage commented 4 years ago

You're very welcome :) btw if you want to use code from Zettlr feel free! And thanks, obviously :)

And thanks for the hint to HyperMD, something like this seems unavoidable for Zettlr as well! Currently there are like a thousand modes at the same time — no performance issues, but certainly not well-written either :D

This way, codeblock classes are added directly with the parser, which is IMO the most performant solution

Absolutely, but as you correctly said, re-writing modes is not as easy as adding overlays …