[posted to four newsgroups, followups set to
netscape.public.mozilla.performance]
 
Mail Reply Performance Status

A couple of weeks ago I made a patch to the editor to streamline
mail reply performance as much as possible. The patch for this is
attached to bug 35295. This note summarizes performance with this
patch.

Mail Reply performance has been slow in mozilla for a few reasons.
One of the main ones is that when mail compose creates the compose
window, it depended on the editor to insert the quoted mail reply.
Inside the editor this went through the same code path as any
other html paste. HTML paste in the editor is complicated. A lot
of work is done that may not be needed when inserting a mail
reply. My patch creates a separate, simplified code path for
insert html in situations where you don't want this additional
work, and makes InsertCitedQuotation() use this simpler code path.

Summary for Those Who Don't Want To Read All This

>31 seconds to respond to a 4000 line message (text + breaks).
7 seconds from mail creating an editor to when it hands off the quote to 
editor
1.6 seconds for parser to convert html stream into a document fragment
18.4 seconds for content to insert the document fragment into the 
document
3.45 seconds for layout to reflow the document
0.45 seconds for painting document

More Details

The Test Case

Mail Reply performance degrades dramatically when replying to
messages that have a large number of dom nodes that are all
children of the body. So for this test I replied to a html message
that was 4000 lines of text, each line separated by a break node
<br>. The machine I used was my 300 MHz G3 mac portable. The build
I used was a debug build of the tip, patched as described, and
with some instrumentation calls added. The instrumentation impact
on the results is not significant, but using a debug build is
(don't know how much of a difference there).

>From Mousedown to Mail Compose Creating the Editor

It's worth looking into how long it takes to get from clicking on
the "Reply" widget to Mail Compose actually creating an editor for
the message body. I suspect it is a significant amount of time. I
didn't investigate it - mail folks may want to do this.

Editor Creation and Initialization

Editor creation and Editor Initialization are pretty fast here.
Construction took 50 microseconds. Init took 25 milliseconds.

>From Mail getting a finished Editor to Mail calling InsertCitedQuotation

Once the editor is up mail compose has to get ready to insert the
data into the editor. I don't know the details of what is
happening here (is it all Mime stuff? Is this when the original
message is pulled over the wire if it hasn't been previously?). It
takes 7 seconds, which is a rather long time and a big part of the
overall time. Mail folks may want to profile this and look for
improvements.

Inside nsHTMLEditor::InsertCitedQuotation

At this point mail compose hands off the html for those 4000 lines
to the editor. This is the part of the process my patch has
streamlined. Only four things happen inside the editor from this
point on. The first is handled by the parser. The remaining three
are handled by content/layout. 

Parsing the HTML for the Quote

The first step is to convert the text stream of html into an
object suitable for insertion into the DOM.
CreateContextualFragment() does this. It's an nsIDOMNSRange call,
but it really falls through to the parser. The parser builds up a
DOM Document Fragment from the html stream. This takes 1.6 seconds
in this test.

Inserting the Document Fragment into the DOM

Next we huck the docfrag into the document using the content call
nsIDOMNode::AppendChild(). This takes a whopping 18.4 seconds.
Layout folks can tell you better than I what is happening here,
but I do know that in addition to moving the 8000 nodes in the
document fragment into the mail compose document, it is also
creating frames for those 8000 nodes and firing off a lot of
content changed notifications. I know the process of moving the
nodes into the document can be speeded up, and I believe that the
notifications can be largely coalesced. I'm not sure if any
improvements can be made to frame construction. Johnny Stenback is
working on this.

Reflow

Next reflow is enabled on the editor. It was off before this so
that we would only do one reflow after the document is fully
created. Reflow takes 3.45 seconds, which is a pretty long time.

Paint

After reflow, we enable view updating on the editor. I believe
this is where painting is happening. It takes 0.45 seconds.

Whats Missing

My patch rips out some things that we may not want ripped out. The
first thing is that I'm not going through the transaction manager
when we insert the docfrag. This means the operation is not
undoable. That's not important for mail quoting because we don't
want that undoable, and in fact mail compose turns off undo on the
editor until it is finished building up the message. But if wanted
to use this simplified codepath for other "live" editor actions
then I should go through the transaction manager. I strongly
suspect that doing so will add very little time. If I'm right
about that I'll put in an updated patch to that effect later.

Also removed is some editor postprocessing. This postprocessing
was time intensive: if I put it back in it would add about 6
seconds to the total time. The two things that mattered here were
replacement of preformatted newlines with break nodes, and
insertion of break nodes into empty list items and table cells.
Both of these steps used to be done for the same reason: to avoid
deadspace in the message where the user would be unable to get a
caret by clicking. Blank lines caused by newlines in preformatted
html, and empty list items and table cells, all suffer from this
problem. converting such newlines to breaks gives the same visual
effect, and allows any blank lines to be clicked in. Similarly,
adding a single <br> node into an empty list item or table cell
has no visual effect, but again allows caret placement when the
user clicks there.

I have looked into the performance of the postprocessing before,
and I know how to speed it up the checks. The result would be that
it would not be terribly expensive to make these checks, if the
document didn't actually need the changes. Ie, the scanning could
be made much faster than it is. However, if the document needed
many such changes, it would still be time intensive. This is
because we would have to make thousands of changes to the dom, and
that is expensive. To improve that I will need help from layout
folks.

There are two things off the top of my head that could be done to
avoid this problem entirely.  The first and most obvious is to do
the work in the frame code and caret code to allow us to get a
caret in these problem areas. Then we don't have to do any of
this.

The second is we could make a funky flavor of the parser to use
here that actually did these conversions/insertions on the fly as
it scanned the html stream.  That would be a LOT faster than
beating on the DOM afterwards.

-- 
jfrancis         .com      -and-     floppymoose         .net
        @netscape                               @netscape

Reply via email to