Closed Bug 35294 Opened 25 years ago Closed 23 years ago

PERF: nsIDOMNode::InsertBefore() performance.

Categories

(Core :: DOM: Core & HTML, defect, P3)

defect

Tracking

()

RESOLVED FIXED
mozilla0.9.6

People

(Reporter: mozeditor, Assigned: jst)

References

Details

(Keywords: dom1, perf, Whiteboard: [HAVE FIX])

Attachments

(8 files)

I've broken out editor Paste performace into 5 bugs. This one is about the InsertBefore() bottleneck. There are two issues here: 1) We have to call InsertBefore() twice for each line of text we paste. This is because we have to replace newlines with <br> nodes. This is done because otherwise we cant draw a caret on blank lines. If we had a frame for blank lines caused by newlines, then we wouldn't need to call InsertBefore() so much, so that's one possible way to address this performance problem. 2) InsertBefore() is taking 18+ milliseconds on my 300mHz G3 Portable. The time taken slowly creeps upward as later lines are pasted in. I assume that scannig through the lengthening child list as hundreds of nodes are inserted is what causes the creep upwards. Any speed improvement to InsertBefore() is a big win for us in Editorland.
Blocks: 28783
ignore the 18+ milliseconds figure. I meant 1.8 ms. Your milage may vary. What is true though is that the loop for chucking the text and breaks into the dom is bound by InsertBefore() performance, and that loop is a big piece of the time for paste (and once we've fixed some editor and caret perf problems, it should make up most of the paste time).
Block/inline problem so reassigning to Buster
Assignee: troy → buster
M18. I know I won't get to this for beta 2. Don't know where it falls in priority order for FCS.
Status: NEW → ASSIGNED
Target Milestone: --- → M18
redistributing bugs across future milestones, sorry for the spam
Target Milestone: M18 → M19
Keywords: perf
marking FUTURE. Unless this shows up as a major performance issue for a common task, it won't be looked at any time soon. Joe, can you provide any hard data to change my mind? "nsIDOMNode::InsertBefore() degrades exponentially with the number of lines" or "nsIDOMNode::InsertBefore() takes up 75% of the time to do any paste operation" or something like that?
Target Milestone: M19 → Future
i have a nice graphic of where time is spent in paste that i'll bring to you.
Joe - If I'm understanding this correctly, you're looking at a performance problem when pasting multiple lines of text at once. My understanding (from the text above) of what you're currently doing is that you are doing insertBefore() for each line, and for the BR after it. A possible solution (which *should* be faster, and I would think could be made faster if it is not) to this on your end could be to append all of the stuff into a DocumentFragment object, and then call insertBefore on the DocumentFragment. See the DOM spec at http://www.w3.org/TR/DOM-Level-2/core.html#ID-952280727 (insertBefore) http://www.w3.org/TR/DOM-Level-2/core.html#ID-B63ED1A3 (documentFragment) It's worth looking at the code that would do this and making sure that it is fast or can be made fast before plunging ahead with this (although actually I wouldn't think it would be all that hard...). If you have any questions, I might be able to help, although my knowledge in this area is mainly about the DOM itself rather than our implementation of it.
Component: Layout → DOM Level 1
insertBefore's implementation is O(n) with respect to the number of lines in the target: 1. due to the call to nsVoidArray::IndexOf(), which must scan the void array to find the element. http://lxr.mozilla.org/mozilla/source/layout/base/src/nsGenericElement.cpp#1903 2. due to the call to nsVoidArray::InsertChildAt(), which requires O(n/2) to shift elements and create space for the new element. http://lxr.mozilla.org/mozilla/source/layout/base/src/nsGenericElement.cpp#1985 I think dbaron is right on the money with respect to how to improve performance for this. Assigning back to jfrancis for investigation.
Assignee: buster → jfrancis
Status: ASSIGNED → NEW
sounds like a plan. I had considered something like this before but didn't know about document fragments, so I didn't have a way to use Append().
Status: NEW → ASSIGNED
However, looking at the current implementation of insertBefore, it may not be optimized for inserting documentFragments, something that probably could be done. In particular, it calls insertChildAt for every child inserted. That implementation *is* a peformance bug that could be improved (although it might be a little messy). Probably the two issues of: * speeding up documentFragment insertion * making editor paste use documentFragments should be separate bugs.
Depends on: 43863
ooof. Ok, it makes no sense to spend time on making the editor use docfrags until they are a performance improvement. Given their current implementation, it would actually degrade performance to use them. I've opened a new bug 43863 for that issue and marked it as a blocker for this bug.
No longer depends on: 43863
adding the blocker info
Depends on: 43863
Blocks: 53252
No longer blocks: 28783
Keywords: mailtrack
I'd like to nominate this for nsbeta1. I think this is one of the bugs that affects message reply performance due to inserting text (if it's not one of the bugs then ignore the nsbeta1 nomination and let me know). reply performance is one of our key areas and it looks like Jean-Francois data shows that we'd get a big win if we could speed up inserting text.
Keywords: nsbeta1
Keywords: dom1
Component: DOM Level 1 → DOM Core
nom catfood: with the mail perf landing, this is about to become the biggest remaining mail perf problem. (Is this the active bug or is there another somewhere?)
Keywords: nsCatFood
Assignee: jfrancis → jst
Status: ASSIGNED → NEW
QA Contact: petersen → desale
not sure why waterson assigned this back to me long ago. The issue described here is a layout problem. While I know there are editor performance issues as well, we really need a faster way to beat on the dom tree without firing off so many duplicate content notifications, etc. cc'ing me and assigning to layout
Keywords: nsbeta1nsbeta1+
Target Milestone: Future → mozilla0.9.1
*** Bug 43863 has been marked as a duplicate of this bug. ***
*** Bug 74907 has been marked as a duplicate of this bug. ***
Blocks: 22486
Blocks: 74912
moving to TM of 0.9.2 per PDT triage (you can check it into 0.9.1 until Friday, 18/May/01 or into 0.9.2 after the tree opens)
Target Milestone: mozilla0.9.1 → mozilla0.9.2
Johnny, will this help with the AppendChild() case as well? That ends up being the one usually hit in mail reply. InsertBefore() work is not wasted though and will help us elsewhere.
Joe, AppendChild() calls InsertBefore() so yes, this will benefit both thoese cases.
This improves my 4000 line mail reply testcase. The AppendChild() call the editor makes is 15% faster with this patch. Thanks!
Updating QA contact to Shivakiran Tummala.
QA Contact: desale → stummala
Joe, can you run the same tests with the new patch I attached? The new patch only contains the changes to nsGenericElement.cpp, you also need the other changes in the first patch in this bug. The new patch should cut down the notifications we make to the document to 1 single call to nsIDocument::ContentAppended() when *appending* a document fragment (in stead of calling nsIDocument::ContentInserted() for every node in the document fragment). This is about as far as we can optimize appending of document fragments in the DOM code (we could still get rid of some reallocing of child pointer arrays, but that's hardly where we spend most of the time), any further optimizations need to happen in layout land (i.e. frame construction)...
CC Putterman, someone on the mail team needs to be helping with this issue. If this proves out, then we should push to get all the existing reply speed fixes incorporated.
Johnny, please merge these patches. They conflict.
C:\moz_src\mozilla\content\base\src>patch <jstpatch4.txt patching file `nsGenericElement.cpp' Hunk #1 succeeded at 2400 (offset 207 lines). Hunk #2 FAILED at 2419. 1 out of 2 hunks FAILED -- saving rejects to nsGenericElement.cpp.rej Yeah, I couldn't patch the last patch (http://bugzilla.mozilla.org/showattachment.cgi?attach_id=37337) But I am building with the other patches and will export this opt build down to the lab and run my perf tests against msgreply.
Can we have new patches that work. Thanks
latest patch gets AppendChild down to 2.62 seconds in my test scenario, down from over 16 seconds. Cool beans.
Moving to mozilla0.9.3
Target Milestone: mozilla0.9.2 → mozilla0.9.3
Moving to mozilla1.0
Target Milestone: mozilla0.9.3 → mozilla1.0
Back to mozilla0.9.3 per high demand for this fix, this still needs some more work to handle errors more gracefully before this is checked in...
Status: NEW → ASSIGNED
Target Milestone: mozilla1.0 → mozilla0.9.3
Target Milestone: mozilla0.9.3 → mozilla0.9.4
a question about content, editor and nsVoidArray (used heavily): does it make sense to add some type of way to insert multiple entries instead of doing them one at a time? Perhaps RemoveElementsAt(index,count) and InsertElementsAt(index, ????)? Or perhaps adding a call to the new nsVoidArray::ExpandTo method would allow us to do all the growing at once; the overhead for adding the elements would only be in shifting elements after the insertion point. Currently the overhead includes the expense of (possibly several) reallocations and copies. All we need is a count of the (likely) number of nodes we'll add. Certainly when adding DocumentFragments that's possible. I'm not certain how much we gain here since I haven't seen a jprof/quantify output for this case, but it's a pretty straightforward and general optimization.
I've added (in the 90545 patch) support for Inserting and removing multiple elements at once. Also, nsSupportsArray now supports SizeTo(). After these patches are merged, we may want to try using these new calls.
Moving to mozilla0.9.5
Target Milestone: mozilla0.9.4 → mozilla0.9.5
Blocks: 28783
What is the status of this work? Though it was decided not to take the sum total of the mail-reply perf branch work, some of the pieces will help out with editor performance in general, This patch is one. Can we have this in 095?
Target Milestone: mozilla0.9.5 → mozilla0.9.6
Blocks: 63759
To repeat: ------- Additional Comments From jfrancis@netscape.com 2001-09-23 23:54 ------- What is the status of this work? Though it was decided not to take the sum total of the mail-reply perf branch work, some of the pieces will help out with editor performance in general, This patch is one. Can we have this in 095? ------- Perhaps for 0.9.6?
Whiteboard: [HAVE FIX]
Being pretty up on array references, that all looks pretty good to me. I agree that the IndexOf case is not a performance issue, since it shouldn't be hit often/ever. r=rjesup@wgate.com
Comment on attachment 55867 [details] [diff] [review] This should be "The One" This looks like a neat performace win, especially for the case when a fragment is appended r=sicking
Ahem, hmm, I forgot that I already had a review for this patch, sorry to request one more Sicking. Well, the more the merryer, right? :-)
Fix checked in.
Status: ASSIGNED → RESOLVED
Closed: 23 years ago
Resolution: --- → FIXED
Component: DOM: Core → DOM: Core & HTML
QA Contact: stummala → general
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: