Home About Eric Topics SourceGear

2003-08-29 12:00:00

Profiler=Good, RichTextBox=Bad

Call me a fan of the Ants Profiler from Red Gate Software. 

Our top priority at SourceGear right now is making Vault faster.  I don't get to do much coding these days, so I decided to get my hands dirty and pitch in.  Several of the other folks here have been using Ants to profile Vault, so I thought I would give it a try.  The tool was extremely smooth.  I installed it with no problems.  I didn't read a word of the documentation.  I launched the profiler and told it to profile the Vault GUI client EXE.  I did my test and exited the Vault client.  Ants showed me the results.

The results browser is cool.  I cruised around the various functions and examined the timings.  Soon I discovered one of those problems which profilers were born to find:  The .NET RichTextBox class is really, really slow.

We use a RichTextBox to display user messages in a pane at the bottom of the Vault client window.  I suppose any plain text box would suffice, but we do use a little bit of color for highlighting errors in red.  Anyway, the profiler was showing that Vault spends an obscene amount of time showing user progress messages.  My test case involved the retrieval of 6,000 files from a repository, which means I was adding 6,000 messages to that RichTextBox.

At first I suspected string concatenation.  The code to append messages looked something like this:

AppendText("["+msg.When+"] "+msg.Message+"\r\n");

So I changed it to eliminate the string concatenation:

AppendText("[");
AppendText(msg.When);
AppendText("] ");
AppendText(msg.Message);
AppendText("\r\n");

This made no real difference in performance, but the profiler results became even more useful.  Ants can show how much time is being spent on each line of code.  When I broke things up, Ants reported that the first four calls to AppendText were fast, and the fifth one was slow.  Then I realized what's going on.  When you append a CRLF to the RichTextBox, it's re-running its internal layout algorithm.

RichTextBox is obviously overkill for the way we are using it.  It's not like we need full justification or embedded tables in our user messages pane, but we're paying for these features in performance.  This innocent-looking piece of the .NET framework is actually a word processor.

The problem was easily fixed.  Instead of calling AppendText() on every single message, I batched up the non-urgent messages into groups so we could append them with a single call.  Much faster, no lost functionality, everybody will be happier.