[Bug 13355] Richedit very slowly open big text files

wine-bugs at winehq.org wine-bugs at winehq.org
Wed Oct 29 19:36:31 CDT 2008


http://bugs.winehq.org/show_bug.cgi?id=13355


Dylan Smith <dylan.ah.smith at gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |dylan.ah.smith at gmail.com
           Keywords|download, source, testcase  |




--- Comment #14 from Dylan Smith <dylan.ah.smith at gmail.com>  2008-10-29 19:36:30 ---
== Diagnosis ==

I looked into it, and I found that most of the time was spent wrapping the
text.  The more wrapping that occurs, the slower it takes, so it will take less
time with a smaller font size or larger window.

I tried to find out what was taking a long time with wrapping, and I noticed
that it was wrapping the entire document 4 times when handing WM_SETTEXT.

1. The text is wrapped as required when it is initially set in WM_SETTEXT.

2. After the text is set ME_UpdateScrollbar is called while processing
WM_SETTEXT.  Previously there was no scrollbar shown, and the wrapped text is
larger vertically than the window, so the scrollbar is shown with
ShowScrollBar.  This sends a WM_SIZE message to the richedit control where it
unconditionally wraps all the text.

3. After wrapping all the text while processing WM_SIZE, ME_UpdateScrollbar is
called again.  Since this WM_SIZE message is being processed immediately, the
scrollbar state stored in the richedit control has not been updated yet, so the
bScrollBarWasVisible variable is set to TRUE, and it calls ShowScrollBar (which
does nothing) and then wraps all the text.

4. Once WM_SIZE is finished, ME_UpdateRepaint continues.  As mentioned in #3,
all the text is wrapped after calling ShowScrollBar.

== Proposed Solution ==

There are a few mistakes the code made that could be corrected:
1. WM_SIZE should only re-wrap the document if the horizontal width changes.
2. ME_UpdateScrollbar should call ShowScrollBar after updating the it's
internal copy of the scrollbar state.
3. ME_UpdateScrollbar should use the fact that WM_SIZE is called by
ShowScrollBar (although this should be tested to ensure it is consistent with
Windows)

This would still leave 2 re-wraps, but the first one was only needed to find
out that scrollbar would be shown.  This first re-wrap could be interrupted
when it gets to a paragraph that is below the end of the view, and realizes the
scrollbar will be shown.  This would only leave a relatively small overhead in
wrapping a large document.


Lastly, I noticed that a lot of the time was probably wasted on memory
allocated, deallocation, and copying text.  This is because paragraphs are
split into runs, where a run is a continuous string of text (i.e. not spanning
multiple lines) with the same style (e.g. font, size, weight, etc.).  Each
re-wrap consists of two phases, one is joining the runs as if they are on the
same line, and the second is splitting the runs at line breaks.

Splitting runs means the string is split into two chunks of memory, where the
second one is newly allocated, and the text in the string after the split is
copied into the newly allocated memory.  Each split is independent, so this is
repeated for each line of a paragraph.

This leads to excess memory being allocated since run for the first line of a
paragraph will have enough space for all the lines of the paragraph.  The
second line will have enough space for all but one of the lines of the
paragraph... and so on.  This leads to allocating an amount of memory of
approximately N*(N/2) compared to N for the text itself.  The memory copying
for the split happens in a similar manner, with the first step involving
copying all but the first line of the paragraph into the memory for the second
line.

This memory allocation, deallocation and copying of text could be cut down if
the same string could be shared amongst multiple runs (lines in this case) in a
paragraph.  The run would then contain a pointer to a position in the string,
the style of the text, and any other information about how to display that
section of the string.

This would avoid a lot of processing, but would need some redesign of the code
to manage it properly (e.g. you can't free the memory for the string of one run
independently of the others). The simplest solution would be to use one string
per paragraph. This may slow insertions for large paragraphs, but it would make
up for it with the less time needed to wrap the paragraph.


-- 
Configure bugmail: http://bugs.winehq.org/userprefs.cgi?tab=email
Do not reply to this email, post in Bugzilla using the
above URL to reply.
------- You are receiving this mail because: -------
You are watching all bug changes.



More information about the wine-bugs mailing list