Optimize .NET development with these performance tips

The .NET Framework offers countless ways to approach and solve a problem, but one may be better than another depending upon performance. Learn a few performance tips to use on your next development project.

The .NET Framework class library is vast and sometimes overwhelming. As with any development language there are numerous ways to solve a problem, but some methods are better than others. I'll examine a few areas where performance may be improved by using a set approach.

When to throw an exception

Exception handling is a key aspect of .NET development. It allows you to easily and gracefully recover from errors that could easily crash an application, but they can be expensive in terms of system resources. For this reason, you should exercise restraint when using exceptions in your applications.

Now, the number of try/catch blocks within your code does not indicate the number exceptions generated by the code. The catch block is only executed when an actual exception is encountered. Also, exceptions should not be used to control program flow. I've seen developers throw exceptions to abort a loop, like the following C# sample:

classExceptionTestClass {
static void Main(string[] args) {
try {
for (int x=0; x < 100; x++) {
if (x == 50) throw new Exception();
} }
catch {}
} }

Notice that the catch block does nothing so program execution continues. The proper way to address this situation is by using a break statement:

classExceptionTestClass {
static void Main(string[] args) {
try {
for (int x=0; x < 100; x++) {
if (x == 50) break;
}  }
catch {}
} }

Here's the equivalent approach in VB.NET:

Sub Main()
Dim x As Integer
For x = 0 To 99
If (x = 50) Then
Exit For
End If
Next x
End Try
End Sub

Microsoft does include the perfmon tool that may be used to monitor the exceptions thrown by an application. It may surprise you to find that certain areas of your application throw more exceptions than you expected. For better granularity, you can also check the exception number programmatically by using Performance Counters.

Working with strings

When a string is altered, the original string is garbage collected with a new object created to hold the changed string. This may not be an issue for a small number of changes, but an excessive number can tax the system.

As with Java, the .NET Framework includes a special class to be used when manipulating string objects: StringBuilder. The StringBuilder class includes methods for altering its contents. It is contained in the System.Text namespace. The following VB.NET sample shows it being used.

Imports System.Text
Module MainModule
Sub Main()
Dim temp As StringBuilder
temp.Replace(".net", ".com")
temp.Append(" rules!")
End Sub
End Module

And here's the C# equivalent:

using System.Text;
namespace Builder {
class SBClass1 {
static void Main(string[] args) {
StringBuilder temp = new StringBuilder();
temp.Replace(".net", ".com");
temp.Append(" rules!");
} } }

There are a few tradeoffs. There is overhead associated with creating a StringBuilder object, both in time and memory. On a machine with fast memory, a StringBuilder becomes worthwhile if you're doing about five operations. As a rule of thumb, I would say 10 or more string operations are a justification for the overhead on any machine, even a slower one.

Working with databases

It is important to use the appropriate data provider when connecting to a database. For example, you should use the SQL managed provider rather than the ODBC provider. Likewise, you should use the proper provider when working with other systems like MySQL, Oracle, DB2, and so forth. Using a generic provider like ODBC introduces another layer of complexity that will slow down data operations.

Another often cited issue is knowing when to use DataReader as opposed to DataSet objects. As a rule, if you don't need the data once it has been read then use a DataReader. The DataReader offers a forward-only trip through data, whereas DataSet allows you access to a group of data that may be necessary to populate an ASP.NET Repeater or similar control.

On the database side, you should use stored procedures whenever possible. This puts the processing load on the database server. Set up stored procedures to handle inserts, updates, and deletes with the data adapter. Stored procedures do not have to be interpreted, compiled, or even transmitted from the client. In addition, they cut down on both network traffic and server overhead.

Take out the trash

While the garbage collector is an excellent feature of the .NET Framework, it often needs help to determine when an object is ready for garbage collection. You can provide help by calling the Dispose method whenever it is available on objects as soon as possible. On the same note, you should not reference objects once they are no longer needed. The reason is the garbage collector will not process them if they are referenced.

Performance matters

The performance factor will increase with the size of an application. The few items covered in this article may not prove useful in a small program, but as your program grows, these items will be useful for streamlining application performance. On the other hand, you should keep these issues in mind during initial development so tweaking performance will not be such an issue down the road.

TechRepublic's free .NET newsletter, delivered each Wednesday, contains useful tips and coding examples on topics such as Web services, ASP.NET, ADO.NET, and Visual Studio .NET. Automatically sign up today!

About Tony Patton

Tony Patton has worn many hats over his 15+ years in the IT industry while witnessing many technologies come and go. He currently focuses on .NET and Web Development while trying to grasp the many facets of supporting such technologies in a productio...

Editor's Picks

Free Newsletters, In your Inbox