Problem. You want to write strings directly to the Response buffer in ASP.NET. Every developer has had to write text with Response.Write at some time. Solution. Here we improve Response.Write calls to be clearer and faster, and benchmark the results.
=== Response.Write method in ASP.NET performance ===
20000 iterations.
Method A: 1568 ms
Note: Concats string parameter of Response.Write.
Method B: 1614 ms
Note: Appends data to StringBuilder than writes that.
Method C: 1474 ms
Note: Writes each part of data individually to Response.
Method D: 1318 ms
Note: Same as Method C except...
Uses UNIX newline instead of Windows newline.
Method E: 1200 ms *
Note: Stores HttpResponse as local variable.
Only accesses Response property once.
* Is an estimate; was taken on different scale.Here I will assume you aren't using string appends and are already using Response.Write. The following code is the version I improved. It walks through Dictionary keys. It is the slow version.
//
// A. Slow version (1568 ms)
//
foreach (var pair in _diskDictionary)
{
Response.Write(pair.Key + ":" + pair.Value.ToString() + Environment.NewLine);
}Even slower version. I tried eliminating the repeated Write calls and simply use a temporary StringBuilder. I varied the capacity of the StringBuilder, but this next code is as good as I got it. [C# - StringBuilder Secrets - dotnetperls.com]
//
// B. Slower version (1614 ms)
//
StringBuilder builder = new StringBuilder();
foreach (var pair in _diskDictionary)
{
builder.Append(pair.Key).Append(":").Append(pair.Value.ToString()).AppendLine();
}
Response.Write(builder.ToString());Faster version. What I changed here: I split up the Response.Write calls to send one argument at a time and not concatenate anything beforehand. This was a substantial speedup.
//
// C. Faster version (1474 ms)
//
foreach (var pair in _diskDictionary)
{
Response.Write(pair.Key);
Response.Write(':');
Response.Write(pair.Value.ToString());
Response.Write(Environment.NewLine);
}Fastest version. The final improvement in this code I made was change the newline to be a simple '\n' character. This changes the output but in this case it didn't matter.
//
// D. Fastest version (1318 ms)
//
foreach (var pair in _diskDictionary)
{
Response.Write(pair.Key);
Response.Write(':');
Response.Write(pair.Value.ToString());
Response.Write('\n');
}I ran the above code fragments 20,000 times each with a dictionary of 180 key/value pairs. The output file was 4 KB and I used Response.Clear() to erase the buffer each time. [See graph at top]
After writing this article I discovered a better way to use Response.Write. I looked carefully at the Response object in Reflector, and it is accessed through a property. Properties are slower than local instances.
The fastest yet. We can cache the Response object locally, and performance improves by nearly 10% in my benchmark. The numbers I measured here were 748 before and 671 after (on a smaller data set).
//
// E. Faster than fastest version
//
HttpResponse r = Response;
foreach (var pair in _diskDictionary)
{
r.Write(pair.Key);
r.Write(':');
r.Write(pair.Value.ToString());
r.Write('\n');
}We see how ASP.NET works with the Response buffer. The best approach is to simply pass in each string one at a time. This is faster, uses less memory, and even simpler to read.
Use ToString. I noted a performance degradation when not calling ToString on the int values above. I don't really know why. Response.Write may have slower code for ints.
More resources. Alik Levin has an interesting post with how Response.Write() is faster than alternative methods. This aligns with the Microsoft guidelines linked to above. [Best ASP.NET Performance Winner For Data Binding - blogs.msdn.com]
Finally, let's look at the Improving ASP.NET Performance document from Microsoft. It tells us what we need to know, but here I provide benchmarks and examples. What do Microsoft's guidelines tell us?
Avoid strings. This is pretty obvious, but you don't want to use simple strings to build up output. This would involve the + operator.
Why is Response.Write fast? "Response.Write internally appends strings to a reusable buffer so that it does not suffer the performance overhead of allocating memory...." [Improving .NET Application Performance and Scalability - MSDN]
You can call Response.Write with individual string arguments for the clearest and fastest code. There's a good and a bad way to use Response.Write(), and avoiding string + operations is the good way.