facebook / lexical

Lexical is an extensible text editor framework that provides excellent reliability, accessibility and performance.
https://lexical.dev
MIT License
17.5k stars 1.45k forks source link

Slow Performance in Safari #1938

Closed jclem closed 1 year ago

jclem commented 2 years ago

In Safari, Lexical performance becomes unacceptably slow in as little as ~400 characters in a plaintext document.

This this CodeSandbox as an example. In just a few hundred characters, the latency on my M1 MacBook Air makes the editor difficult to use.

This sandbox is using:

I've been testing with this short document:

1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890

1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890

1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890

1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
merelinguist commented 2 years ago

I can reproduce this on 2019 MacBook Air in Safari 15.4. The latency is especially obvious to me when adding linebreaks. There's a noticeable delay between the character being added and the cursor jumping. This doesn't seem to be a problem in Chrome.

trueadm commented 2 years ago

I have a possible fix for this issue: https://github.com/facebook/lexical/pull/1943

fantactuka commented 2 years ago

Hi @merelinguist do you mind checking if 0.2.5 fixed newlines insertion latency

jclem commented 2 years ago

Update on the original issue: The latency, as I was beginning to suspect, appears to be in paints. In a small browser window, input latency is acceptable. In a large window when lots of text is visible, latency increases sharply.

There may be some relationship with the newlines latency as well—I've noticed that most of the latency happens when whitespace is entered—so typing characters is always fast, but even if I type a space, the entire editor repaints instead of just the line being edited:

https://user-images.githubusercontent.com/412282/166329479-c5bb0d32-6772-4339-9ea1-a8a390020204.mp4

Notice it doesn't appear to happen on all whitespaces inserted, just most of them.

By contrast, in Chrome, newlines result in a full repaint, but not other whitespace:

https://user-images.githubusercontent.com/412282/166329877-df512a7b-3ed3-4e4e-b80d-2e889394c1e3.mp4

Note that this example uses 0.2.5

trueadm commented 2 years ago

Do you observe the same issues with other content editable based text editors? Could it be due to some CSS or feature on the Lexical playground?

jclem commented 2 years ago

Do you observe the same issues with other content editable based text editors? Could it be due to some CSS or feature on the Lexical playground?

Tested in ProseMirror on their homepage demo. Whitespace entry (including new lines) does not cause a full editor paint. Only the line being edited tends to be repainted. The performance in the PM demo remains fast where Lexical begins to exhibit high input latency.

trueadm commented 2 years ago

@jclem It's likely to do with something on the playground then. We have some plugins that do a getBoundingClientRect on selection changing. That could be part of the reason, or it could be some CSS property. Does this occur for you on this example? Have you tried hiding the debug panel (it's in the settings tab, bottom left of screen).

You could also try another example with Lexical, such as: https://codesandbox.io/s/lexical-plain-text-example-g932e

jclem commented 1 year ago

@trueadm Just to clarify, I haven't done any testing in the Lexical Playground itself.

What I have found that is extremely surprising is that setting outline: none on the editor itself vastly improves performance in Safari. I whittled your CodeSandbox down to what I had in mine and eventually found that removing that CSS rule caused yours to inherit the same performance.

To reproduce: Simply remove the outline: 0 rule from the .editor-input selector in your CodeSandbox, and then try editing a document with 500 empty lines. It's a world of difference. I guess outlines are just really expensive to paint in Safari? Not sure.

As far as I'm concerned, this issue is solved for me, but I'll let you close the issue out or not depending on whether you want to take any action here.

trueadm commented 1 year ago

@jclem We let the user define the CSS for their content editable, as outline has clear benefits for accessibility reasons. It can be worked around with a manual outline (which we do on facebook.com etc) but not all users might want to do that. We should maybe flag an issue on the Webkit bug tracker for this, as it sounds like a bad Webkit bug TBH.

Another thing, did you find the outline: none and outline: 0 performed differently?

jclem commented 1 year ago

We let the user define the CSS for their content editable, as outline has clear benefits for accessibility reasons.

Makes sense! I wouldn't expect Lexical to enforce any visual styling.

Another thing, did you find the outline: none and outline: 0 performed differently?

Nah—outline: none and outline: 0 are equivalent, performance-wise, as far as I can tell. I also tested manual outlines with box-shadow and border, and they also perform fine. Looks like outline is the only problematic one.

I agree that a Webkit bug may be a good idea. I think it makes sense to let you all file it, though let me know if I can be of any more assistance isolating or reproducing the problem.

brainkim commented 1 year ago

@jclem Here’s an upstream issue in Webkit if you want to make a fuss there: https://bugs.webkit.org/show_bug.cgi?id=232673

jclem commented 1 year ago

Thanks for the heads up, @brainkim! Will take a look.

sualehasif commented 1 year ago

@trueadm how does facebook.com do a workaround? I tried for a while, but working in a tauri app without fixing this performance issue makes it unusable :(

trueadm commented 1 year ago

We remove the outline from styling as per the discussion above.