Published: Wednesday, January 02, 2002
Performance Metrics for the ASP Response Object, Part 2
By James Greenwood
Read Part 1
In Part 1 we examined three different tests for outputting content.
In this final part we'll look at the timing results from these tests and examine the performance results
using ASP.NET.
The Results
On a PIII, running Windows 2000 and IIS5 (hence ASP 3.0), the results, averaged over three trial runs, are as follows:
- Method 1: 0.534 seconds
- Method 2: 0.721 seconds
- Method 3: 4.297 seconds
As can be seen from this, the performance of context switching is greater than that of any other
technique. This is the opposite of in earlier versions of ASP, where it was common knowledge that
each context-switch was a very expensive operation. As the processing time is on the same order of
magnitude - with Response.Write()ing code taking 50% longer, a decision has to be made
over which is more important to a company - performance, or maintainability. The author's personal
opinion is that processors are relatively cheap when compared to the extra time involved in
maintaining unstructured coding. Additionally, optimizations can generally be made in other areas
that will more than compensate for this performance hit.
The difference in performance between the first two and the third method is the big surprise. It
is easy to assume that using the With block would speed up execution due to having a
more efficient reference to the object. This is clearly not the case, and the performance is an order
of magnitude (10x) slower than that of method 1. This kind of performance hit is generally completely
unacceptable, especially due to the small benefit that is gained in terms of maintainability.
ASP.NET Comparison
One of the main claims about .Net is that the performance offered is vastly superior to that of
traditional ASP. To test that claim, a similar piece of code can be written in ASP.Net, compiled, and
run to see the execution time. The code below is the C# implementation of the algorithm used in
traditional ASP above:
<script language="C#" runat="server">
void Page_Load(object sender, EventArgs e)
{
double dblPeriod = 0.0;
DateTime dteTimer = DateTime.Now;
for (int lngCount = 0; lngCount < 500000; lngCount++) {
Response.Write(".");
}
dblPeriod = TimeSpan.FromTicks(DateTime.Now.Ticks-dteTimer.Ticks).TotalSeconds;
Response.Clear();
Response.Write("Execution time:" + dblPeriod.ToString());
}
</script>
|
As can be seen from this, the functionality of a Timer can be implemented using the DateTime
and TimeSpan classes. This static method of Now in the Timer class can be
called to get the start time, and the elapsed period can be calculated by subtracting the initially
stored time to the time at the end of processing (in Ticks - a Tick being 100 nanoseconds). This value
can then be converted back to fractions of seconds by calling TimeSpan.FromTicks(lngTickCount).TotalSeconds).
When this code is compiled and executed (simply by loading the ASP.NET Web page in a browser), it can
be seen that the performance claims made by Microsoft are justified, with the elapsed period being
around 0.10 seconds. This is only 28% of the execution time of the fastest we could achieve from
traditional ASP.
Using the StringBuilder
The .NET Framework contains a StringBuilder class that was designed to allow for efficient
concatenations of strings, an expensive operation. Many developers write code that continuously builds
a string before outputting it, perhaps in a loop through the contents of a Recordset. Continually
adding onto a string is expensive, though, and the performance pitfalls are great. To learn more about
this problem and how to solve it in classic ASP, be sure to read: StrCat.Catter
- An Efficient String Concatenation Component.
While doing multiple Response.Writes is much faster than building up a string, we can
obtain performance gains of up to 10x by using the .NET Framework StringBuilder class in our
ASP.NET Web pages. A simple example of using this class can be seen below:
<script language="C#" runat="server">
void Page_Load(object sender, EventArgs e)
{
double dblPeriod = 0.0;
DateTime dteTimer = DateTime.Now;
StringBuilder s = new StringBuilder(SIZE);
for (int iLoop=0; iLoop < 500000; iLoop++)
s.Append(".");
dblPeriod = TimeSpan.FromTicks(DateTime.Now.Ticks-dteTimer.Ticks).TotalSeconds;
Response.Clear();
Response.Write("Execution time:" + dblPeriod.ToString());
}
</script>
|
The time required to execute the above script averaged 0.09 seconds. If you attempted to build up
a string with 500,000 characters, one character at a time, the running time would take much longer,
on the magnitude of three full minutes!
Conclusion
The performance of context switching has vastly improved from earlier versions of ASP to ASP 3.0,
making it more efficient than an ASP method call. As the performance of these two styles of
programming are on the same scale, other factors should probably be considered when decided which
technique is appropriate. This cannot generally be said for the third method, where the performance
can be subjectively categorized as appalling.
ASP.Net offers an even greater performance, being between three and four times as fast at completing
the same task, and thirty to forty times faster when using the StringBuilder class. This
is due entirely to the benefits achieved by executing compiled code. With output caching, this figure
will be even more impressive.
As with all benchmarks, this test should not be treated as a definitive comparison of techniques, it
merely provides a quick metric, showing an approximate ordering of performances. Even this should not
be taken out of context - the length of strings involved, the fact that only literals rather than
variables and function calls were involved, and so on, should all be taken into consideration when
comparing performance. Furthermore, performance alone is quite often a misleading way of determining
best coding practices, it this weren't the case, all programming would still be in hand-crafted
assembly-language, making use of the idiosyncrasies of the CPU, shift registers, etc.
By James Greenwood