Performance Issues with ProseMirror and Chrome

Very big documents making things slow is a known issue. If you try to edit the same document in a plain contentEditable element, is it noticeably better?

We have been testing by trying to disable any and all spelling plugins. Its also a little more complicated for our user context as well. How to resolve problems with little user interaction. But, AppleSpell continues to come back up and be annoying. Suck up a lot of CPU cycles randomly but, only seems like Chrome is where it shows up.

Sorry, I’m not sure I understand what you mean by plain contentEditable element. I think the thing that sorta stands out to me is how firefox runs way better than chrome. My intuition is that its browser level issues with performance.

This may not help at all, but might be worth trying the tips at https://discussions.apple.com/thread/8385482 (thought I’d back up those dirs/settings if you don’t want to lose them)

Yeah, we did that too. We found it didn’t really help a whole lot.

I’m running into performance issues with large documents + decorations (non safari / apple OS chrome). I am nearly sure it’s simply due to large amount of visible DOM nodes, nothing in particular able to be optimized via prosemirror source code. I know this because I wrote a prosemirror plugin which sets certain nodes to be hidden via decoration (display: none) and when a large document is loaded but most of the nodes are hidden, performance becomes snappy fast. When unfiltered, there is noticable lag when adding characters / structure.

I’m thinking pagination or some type of smarter occlusion culling is the short / medium term solution. A solution without real time collaboration would be pretty straightforward. But with collaboration, it gets a bit more tricky.

Occlusion culling is difficult because simulating the full height of the scrollable container is indeterminate, and would require at least one real DOM render to predict accurately. I’m pretty sure this is how Google Docs operates (probably some cache layer for the real height while lazy loading)

I acknowledge this thread, Paginated Editing?, where it’s suggested prosemirror lib wouldn’t bake in this type of functionality, but it’s definitely important for the way my app is being used. (There are at least two other threads discussing pagination as well for any interested)

All of this being said, it’d be great to see some type of community plugin that bakes in either pagination and/or occlusion culling support. I’ll see what I could do, but can’t promise anything short term. I’d also be willing to have a discussion with anyone interested in implementing something of the sort.

4 Likes

I did a similar experiment ages ago. I basically load like 30% of this book:

Into the basic example of prosemirror, that is almost 500k words (so is massive).

You can check this on this link: https://cookie-turkey.glitch.me/

You can easily see the difference on performance of chrome vs firefox.

It is, but for me Chrome is doing a lot better on that than Firefox (so that seems contrary to @JCHollett’s experience from the first post).

Just tested on Firefox 72 and Chrome 79 on an old Macbook Air mid 2012 with only 4 GB of RAM, this 500k page works impressively well on Firefox, you can feel some input delay but nothing crazy while it’s indeed quite sluggish on Chrome. I didn’t think there would be such good performance on massive documents like that.

My feeling is that Chrome just has a harder time dealing with it but, It seems like other things might affect performance too.

Tested on linux debian: chrome 80 is not slow, firefox 72 is a bit slow.

Maybe the issue you see happens only on OSX ?

macOS 10.15.3 check of typing near the bottom of the document:

  • Safari 13.0.5: quick
  • Firefox 72.0.2: very slight lag
  • Chrome 80.0.3987.100: significant lag

macOS 10.15.4 with a document that’s ~15000 characters / ~3000 words long (which is not that long):

  • Safari 13.1 and Firefox 72.0.2 show almost no lag.
  • Chrome 81.0.4044.138 and Brave 1.8.90 (also based on Chromium) both show significant lag, enough to be unusable.

This is with no plugins enabled on the editor. I’m seeing almost as bad performance if I copy my entire document into a plain contenteditable element so the problem seems to be with Chromium, not with ProseMirror.

I am nearly certain there is at least one other thread that discusses this issue.

Chrome Linux seems to deal with documents in the million-character range without much trouble, interestingly.

Is there possible to share github gist about the hiding plugin ? :love_you_gesture:

1 Like

This bug report seems relevant to these issues: https://bugs.chromium.org/p/chromium/issues/detail?id=1076718

Lodged by someone at atlassian.com

I’m also seeing the same super slow typing performance on Chrome under Mac OS X with very large documents loaded. Based on profiling I doubt there is much Prosemirror could do to mitigate this, as the vast majority of the time seems to be spent in browser code outside of the javascript runtime. An occlusion hack as previously suggested would probably help given setting display:none on the majority of the document brings typing speed back to mostly acceptable.

Hopefully the Chrome folks can get a fix for this soon, as it is currently making large document editing pretty much unusable on Chrome under MacOSX. Safari performs very well on the same document (and same machine). Firefox isn’t great, and probably borderline acceptable, but certainly a good deal better than Chrome. In my context, I can probably get away with not supporting Safari and Firefox, so I’m not that worried about poor Firefox performance.

For those suffer from poor performance of Chrome, you can try the new property content-visibility of CSS, only available in Chrome 85.

More info in https://web.dev/content-visibility/

1 Like

Thanks @Priestch for the tip.

I found that the framerate was very low in Chrome (both OSX and Linux) when the contenteditable node contains a large number of DOM nodes, and the editor is in focus (no need to type). Confirmed, it can be worked around quite effectively by applying content-visibility: auto; contain-intrinsic-size <stable-last-rendered-size>; to elements that wrap smaller ones.

I am very thankful at this point that the prosemirror document is an immutable object, so its easy to identify when the content of a node has changed and its size needs to be recalculated.

I logged https://bugs.chromium.org/p/chromium/issues/detail?id=1141742, and it looks like in https://bugs.chromium.org/p/chromium/issues/detail?id=892513 some fixes have landed and will be released in Chromium 88!

Hey. Were you ever able to figure this out? I wont be able to easily produce a gist (dont want to copy code base in) but could help step you through the main ideas.