Performance issue with word wrap #11

Open
opened 2014-07-30 17:07:53 -05:00 by Alexx999 · 1 comment
Alexx999 commented 2014-07-30 17:07:53 -05:00 (Migrated from github.com)

I use AvalonEdit to display XML data, and sometimes that data include really long lines without spaces (at most it's 25MB byte[] data encoded as base64).
When I enable WordWrap performance drops really bad.

And even with WordWrap disabled lines are still wrapping after 9600 symbols, so performance drops to unacceptable levels in worst case. Workaround is checking string and splitting lines by 8000 symbols - then performance is OK

I use AvalonEdit to display XML data, and sometimes that data include really long lines without spaces (at most it's 25MB byte[] data encoded as base64). When I enable WordWrap performance drops really bad. And even with WordWrap disabled lines are still wrapping after 9600 symbols, so performance drops to unacceptable levels in worst case. Workaround is checking string and splitting lines by 8000 symbols - then performance is OK
dgrunwald commented 2014-08-09 08:35:11 -05:00 (Migrated from github.com)

This is a known problem. AvalonEdit isn't really designed to handle long lines, and WPF has some strange performance bugs with them -- I tested this some time ago, and WPF rendering time increases linearly with the line length up to some strange font-dependent limit (this might be the 9600 in your case), where it will suddenly start to word-wrap. Increasing the line length above this limit then causes quadratic growth in the time taken.

I'm not sure what causes WPF to act so strangely. Truncating the lines is a good workaround. Note that you don't have to truncate the document text, you can instead truncate by extending the AvalonEdit rendering pipeline:

    public class TruncateLongLines : VisualLineElementGenerator
    {
        const int maxLength = 2000;
        const string ellipsis = "...";
        const int charactersAfterEllipsis = 100;

        public override int GetFirstInterestedOffset(int startOffset)
        {
            DocumentLine line = CurrentContext.VisualLine.LastDocumentLine;
            if (line.Length > maxLength) {
                int ellipsisOffset = line.Offset + maxLength - charactersAfterEllipsis - ellipsis.Length;
                if (startOffset <= ellipsisOffset)
                    return ellipsisOffset;
            }
            return -1;
        }

        public override VisualLineElement ConstructElement(int offset)
        {
            return new FormattedTextElement(ellipsis, CurrentContext.VisualLine.LastDocumentLine.EndOffset - offset - charactersAfterEllipsis);
        }
    }

Usage: editor.TextArea.TextView.ElementGenerators.Add(new TruncateLongLines());

This causes lines to be truncated similar to folding -- the rendering layer only gets to see the truncated text and is more performant, but selecting the whole line and copying it to the clipboard causes the whole text to be copied, not just the truncated version.

Also, for performance:

  • Disable textEditor.Options.EnableHyperlinks and EnableEmailHyperlinks if you don't need them.
  • Don't enable ShowSpaces/ShowTabs
This is a known problem. AvalonEdit isn't really designed to handle long lines, and WPF has some strange performance bugs with them -- I tested this some time ago, and WPF rendering time increases linearly with the line length up to some strange font-dependent limit (this might be the 9600 in your case), where it will suddenly start to word-wrap. Increasing the line length above this limit then causes quadratic growth in the time taken. I'm not sure what causes WPF to act so strangely. Truncating the lines is a good workaround. Note that you don't have to truncate the document text, you can instead truncate by extending the AvalonEdit rendering pipeline: ``` public class TruncateLongLines : VisualLineElementGenerator { const int maxLength = 2000; const string ellipsis = "..."; const int charactersAfterEllipsis = 100; public override int GetFirstInterestedOffset(int startOffset) { DocumentLine line = CurrentContext.VisualLine.LastDocumentLine; if (line.Length > maxLength) { int ellipsisOffset = line.Offset + maxLength - charactersAfterEllipsis - ellipsis.Length; if (startOffset <= ellipsisOffset) return ellipsisOffset; } return -1; } public override VisualLineElement ConstructElement(int offset) { return new FormattedTextElement(ellipsis, CurrentContext.VisualLine.LastDocumentLine.EndOffset - offset - charactersAfterEllipsis); } } ``` Usage: `editor.TextArea.TextView.ElementGenerators.Add(new TruncateLongLines());` This causes lines to be truncated similar to folding -- the rendering layer only gets to see the truncated text and is more performant, but selecting the whole line and copying it to the clipboard causes the whole text to be copied, not just the truncated version. Also, for performance: - Disable textEditor.Options.EnableHyperlinks and EnableEmailHyperlinks if you don't need them. - Don't enable ShowSpaces/ShowTabs
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
gh-icsharpcode/AvalonEdit#11
No description provided.