Bug 49040 - Pasting large amounts of plain text in a text area is very slow
Summary: Pasting large amounts of plain text in a text area is very slow
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: HTML Editing (show other bugs)
Version: 528+ (Nightly build)
Hardware: All OS X 10.5
: P2 Normal
Assignee: Enrica Casucci
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2010-11-04 17:04 PDT by Enrica Casucci
Modified: 2010-11-05 17:15 PDT (History)
4 users (show)

See Also:


Attachments
Test (48 bytes, text/html)
2010-11-04 17:04 PDT, Enrica Casucci
no flags Details
Patch (1.61 KB, patch)
2010-11-04 17:11 PDT, Enrica Casucci
no flags Details | Formatted Diff | Diff
Patch2 (1.96 KB, patch)
2010-11-05 13:42 PDT, Enrica Casucci
no flags Details | Formatted Diff | Diff
Patch3 (2.00 KB, patch)
2010-11-05 16:51 PDT, Enrica Casucci
adele: review+
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Enrica Casucci 2010-11-04 17:04:11 PDT
Select a large amount of plain text (~500k) from a file and copy
Open the attached file.
Paste into the text area.

Result: the browser hangs for several seconds.
Comment 1 Enrica Casucci 2010-11-04 17:04:40 PDT
Created attachment 73006 [details]
Test
Comment 2 Enrica Casucci 2010-11-04 17:11:26 PDT
Created attachment 73007 [details]
Patch
Comment 3 Adele Peterson 2010-11-04 17:20:51 PDT
Comment on attachment 73007 [details]
Patch

Would we also want this optimization if we're pasting into any element that has user-modify: read-write-plaintext-only set?
Comment 4 Alexey Proskuryakov 2010-11-04 23:21:41 PDT
See also: bug 34237 (a case of slow pasting that Enrica fixed a few months ago).
Comment 5 Ryosuke Niwa 2010-11-04 23:34:35 PDT
Comment on attachment 73007 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=73007&action=review

> WebCore/ChangeLog:11
> +        pasting into a text area. What we really avoid is iterating through
> +        a large number of paragraph when no style change is needed.

"What we really avoid is iterating through..." sounds confusing to me.  Maybe just "We avoid iterating through..."?

> WebCore/editing/ReplaceSelectionCommand.cpp:1164
> -        if (m_matchStyle) {
> +        if (m_matchStyle && !isNodeInTextFormControl(start.node())) {

Isn't better to set m_matchStyle=false right at the front if we're in a text form control?  Is there a case we need m_matchStyle=true even when we're in a text form control?
Comment 6 Tony Chang 2010-11-05 10:03:58 PDT
It might be possible to write a perf test for this (seems like the time should be constant or linear).  See LayoutTests/resources/magnitude-perf.js and LayoutTests/perf.
Comment 7 Enrica Casucci 2010-11-05 10:23:43 PDT
(In reply to comment #3)
> (From update of attachment 73007 [details])
> Would we also want this optimization if we're pasting into any element that has user-modify: read-write-plaintext-only set?

I'll look into it.
Comment 8 Enrica Casucci 2010-11-05 10:27:59 PDT
(In reply to comment #5)
> (From update of attachment 73007 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=73007&action=review
> 
> > WebCore/ChangeLog:11
> > +        pasting into a text area. What we really avoid is iterating through
> > +        a large number of paragraph when no style change is needed.
> 
> "What we really avoid is iterating through..." sounds confusing to me.  Maybe just "We avoid iterating through..."?
> 
Not sure that what you suggest is less confusing. I can rephrase this.
The point I'm trying to make is that the performance hit comes from the paragraph iteration.

> > WebCore/editing/ReplaceSelectionCommand.cpp:1164
> > -        if (m_matchStyle) {
> > +        if (m_matchStyle && !isNodeInTextFormControl(start.node())) {
> 
> Isn't better to set m_matchStyle=false right at the front if we're in a text form control?
I believe it makes no difference, this is where we apply the style, if we check here we skip applying the style.
  Is there a case we need m_matchStyle=true even when we're in a text form control?
No. In general we wouldn't need to apply the style when pasting plain text except for the case where we want to preserve the typing style.
Comment 9 Enrica Casucci 2010-11-05 10:30:41 PDT
(In reply to comment #6)
> It might be possible to write a perf test for this (seems like the time should be constant or linear).  See LayoutTests/resources/magnitude-perf.js and LayoutTests/perf.

This fix doesn't change the performance from non-linear to linear. The performance is linear already.
Do you think this is still worth?
Comment 10 Ryosuke Niwa 2010-11-05 10:51:15 PDT
(In reply to comment #8)
> No. In general we wouldn't need to apply the style when pasting plain text except for the case where we want to preserve the typing style.

Ok, in that case, it's cleaner to set m_matchStyle false if we're in a text form control.  When we don't need this extra condition in the if statement.  I think setting this either when we instantiates ReplaceSelectionCommand or right at the beginning of doApply will also prevent us from needlessly obtaining the computed style.
Comment 11 Tony Chang 2010-11-05 10:53:51 PDT
(In reply to comment #9)
> (In reply to comment #6)
> > It might be possible to write a perf test for this (seems like the time should be constant or linear).  See LayoutTests/resources/magnitude-perf.js and LayoutTests/perf.
> 
> This fix doesn't change the performance from non-linear to linear. The performance is linear already.
> Do you think this is still worth?

It might be fast enough to show up as constant even though it's technically linear.  Another way to think of it is testing to make sure that pasting 500k of text always takes less than X ms.

I'm not sure that magnitude-perf.js will handle this type of test well, Ojan, what do you think?
Comment 12 Ryosuke Niwa 2010-11-05 11:00:58 PDT
(In reply to comment #11)
> It might be fast enough to show up as constant even though it's technically linear.  Another way to think of it is testing to make sure that pasting 500k of text always takes less than X ms.

I'm afraid setting a hard time limit will make this test flaky. I'm okay with not having a test for this change.
Comment 13 Ojan Vafai 2010-11-05 13:19:22 PDT
(In reply to comment #11)
> (In reply to comment #9)
> > (In reply to comment #6)
> > > It might be possible to write a perf test for this (seems like the time should be constant or linear).  See LayoutTests/resources/magnitude-perf.js and LayoutTests/perf.
> > 
> > This fix doesn't change the performance from non-linear to linear. The performance is linear already.
> > Do you think this is still worth?
> 
> It might be fast enough to show up as constant even though it's technically linear.  Another way to think of it is testing to make sure that pasting 500k of text always takes less than X ms.
> 
> I'm not sure that magnitude-perf.js will handle this type of test well, Ojan, what do you think?

The magnitude perf stuff is still pretty experimental (e.g. these tests are skipped on non-chromium bots right now). I welcome people using it and writing new tests, but it's still on my todo list to make the tests more reliable. Given that this patch is not changing the order of magnitude, I probably wouldn't bother in this case.

(In reply to comment #12)
> (In reply to comment #11)
> > It might be fast enough to show up as constant even though it's technically linear.  Another way to think of it is testing to make sure that pasting 500k of text always takes less than X ms.
> 
> I'm afraid setting a hard time limit will make this test flaky. I'm okay with not having a test for this change.

We could at least have a manual test. It's not ideal, but it gives a comparison point that can be used to identify regressions between nightly builds. Eventually, if we have a performance testing framework, we can move this test into it.
Comment 14 Enrica Casucci 2010-11-05 13:42:27 PDT
Created attachment 73111 [details]
Patch2

This is a new patch that addresses Adele's and Ryosuke's comments.
I don't think we need another layout test for this fix, since there are several tests that verify the correct behavior in this case.
Comment 15 Ryosuke Niwa 2010-11-05 14:26:45 PDT
Comment on attachment 73111 [details]
Patch2

View in context: https://bugs.webkit.org/attachment.cgi?id=73111&action=review

> editing/ReplaceSelectionCommand.cpp:804
> +    if (isNodeInTextFormControl(selection.start().node()) || (selection.start().node()->renderer() && selection.start().node()->renderer()->style()->userModify() == READ_WRITE_PLAINTEXT_ONLY))
> +        m_matchStyle = false;

Maybe we should also check the selection end?  Or is there guarantee that this would never happen?
Comment 16 Adele Peterson 2010-11-05 14:31:25 PDT
Comment on attachment 73111 [details]
Patch2

View in context: https://bugs.webkit.org/attachment.cgi?id=73111&action=review

>> editing/ReplaceSelectionCommand.cpp:804
>> +        m_matchStyle = false;
> 
> Maybe we should also check the selection end?  Or is there guarantee that this would never happen?

Is there a need to still do the isNodeInTextFormControl check?
Comment 17 Enrica Casucci 2010-11-05 16:51:49 PDT
Created attachment 73142 [details]
Patch3

All tests pass.
Comment 18 Adele Peterson 2010-11-05 16:55:29 PDT
Comment on attachment 73142 [details]
Patch3

View in context: https://bugs.webkit.org/attachment.cgi?id=73142&action=review

> ChangeLog:19
> +        and force no style matching.

You should update this comment.
Comment 19 Ryosuke Niwa 2010-11-05 16:56:10 PDT
(In reply to comment #17)
> Created an attachment (id=73142) [details]
> Patch3
> 
> All tests pass.

Your patch is made in WebCore/.  Could you remake it in /?
Comment 20 Ryosuke Niwa 2010-11-05 16:58:40 PDT
Comment on attachment 73142 [details]
Patch3

View in context: https://bugs.webkit.org/attachment.cgi?id=73142&action=review

> editing/ReplaceSelectionCommand.cpp:805
> +    if ((selection.start().node()->renderer() && selection.start().node()->renderer()->style()->userModify() == READ_WRITE_PLAINTEXT_ONLY) &&
> +        (selection.end().node()->renderer() && selection.end().node()->renderer()->style()->userModify() == READ_WRITE_PLAINTEXT_ONLY))
> +        m_matchStyle = false;

I'm just curious as to why this is superior to checking that it's in the text form control.  Could you elaborate?  Of course, this patch LGTM nonetheless.
Comment 21 Adele Peterson 2010-11-05 17:00:19 PDT
Its superior because this optimization will apply to other plaintext editable areas besides form controls.
 
(In reply to comment #20)
> (From update of attachment 73142 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=73142&action=review
> 
> > editing/ReplaceSelectionCommand.cpp:805
> > +    if ((selection.start().node()->renderer() && selection.start().node()->renderer()->style()->userModify() == READ_WRITE_PLAINTEXT_ONLY) &&
> > +        (selection.end().node()->renderer() && selection.end().node()->renderer()->style()->userModify() == READ_WRITE_PLAINTEXT_ONLY))
> > +        m_matchStyle = false;
> 
> I'm just curious as to why this is superior to checking that it's in the text form control.  Could you elaborate?  Of course, this patch LGTM nonetheless.
Comment 22 Ryosuke Niwa 2010-11-05 17:03:52 PDT
(In reply to comment #21)
> Its superior because this optimization will apply to other plaintext editable areas besides form controls.

Right, but what are they?  What uses editable region other than contenteditable and forms?
Comment 23 Adele Peterson 2010-11-05 17:08:27 PDT
Any element could have this style.  Just like any element could set "-webkit-user-modify: read-write" to get rich text editing.

(In reply to comment #22)
> (In reply to comment #21)
> > Its superior because this optimization will apply to other plaintext editable areas besides form controls.
> 
> Right, but what are they?  What uses editable region other than contenteditable and forms?
Comment 24 Ryosuke Niwa 2010-11-05 17:09:56 PDT
(In reply to comment #23)
> Any element could have this style.  Just like any element could set "-webkit-user-modify: read-write" to get rich text editing.

That makes sense.  Thanks for the information.
Comment 25 Enrica Casucci 2010-11-05 17:15:23 PDT
Committed revision 71459.