Category: Dotnet/.NET – C#

Update 1/27/2009: I posted an updated version of this article targeted for Silverlight Runtime 2.0 here

Imagine being able to author rich Internet applications in your .NET language of choice, without having to mess with Javascript, cross-browser compatibility issues, or ActionScript. That’s the promise of Microsoft Silverlight 1.1. In this article, I will document my attempt at creating a Silverlight 1.1 “Hello World” application. My Hello World application is a little bit more fancy than the typical one… this one involves some animation, and drawing a few shapes from code.

If you are new to Silverlight, Silverlight 1.1 (currently in Alpha) is the version that will include the .NET CLR and allow you to write Silverlight code with .NET languages such as C#.

Most Silverlight 1.1 C# examples I found on the web use the XAML file to declare and set object properties. In my example, I am going to create and draw most objects from the code behind c# class.

Installing Visual Studio 2008

If you don’t have Visual Studio 2008 already installed. You can download it from here. Downloading and installing Visual Studio 2008 to my Virtual PC took about 3 hours (1 for the download and 2 for the install).

Silverlight Project Files

After the project has been created, you are presented with the default Page.xaml file:

Your Solution should now have the following files:

The two files that you will be working with are Page.xaml and TestPage.html. Page.xaml stores the markup for the design elements (for more info on XAML, see this MSDN article). TestPage.html is the regular HTML page that will host the main Silverlight object. Silverlight.js is the Javascript helper file for Silverlight applications.

For our example, we will be adding code to Page.xaml.cs. This is what Page.xaml.cs looks like initially:

Add Some Code

Ready to write some code (complete source code at the end of the article)? First, we are going to add a Storyboard element to our Page.xaml. This Storyboard element serves as a timer for the animation we are going to display.

And Now, Ladies and Gentlements, My Hello World Silverlight App

Source Code

In a previous article (“StringBuilder is not always faster), I provided some quick benchmark data and gave “rules of thumb” for when to use StringBuilder and when to use traditional string concatenations. In this follow-up article, I will attempt to provide a more detailed analysis.

If you don’t want to bother with the details, jump directly to the conclusions here.

A Look at the Generated MSIL

A reader, Matt, suggested that it’s possible the compiler may have noticed that I never use the generated test objects in my benchmark code and not created them. That would definitely invalidated my test results!

Size of Concatenated Values and StringBuilder with Initial Capacity

More questions from Matt: how does the performance curve change if the concatenated values are larger? And what if you seed the StringBuilder object with an initial capacity?

To answer the questions, I wrote some more benchmarks (complete source code at the bottom of this article) to compare three different methods of concatenation:

“+” concatenation: This is the traditional a + b + c method.

StringBuilder: Create a StringBuilder object using the default constructor and calling Append().

StringBuilder/Pre-allocated: Create a StringBuilder object and preallocate the initial capacity so that it does not need to expand later.

String Size = 10

The chart below shows elapsed times (ms) of the three concatenation methods, with the concatenated string size equaled to 10 characters

As the chart illustrates, when the size of the concatenated value is small (10 characters in this test), “+” concatenation (blue line) performs faster than StringBuilder until the number of concatenations reaches 6. After 6, StringBuilder starts to work exponentially faster.

However, when compared with the StringBuilder/Pre-allocated method, StringBuilder starts to perform as fast as “+” concatenation much earlier: at 3 concatenations.

Note: The orange line for StringBuilder is not very linear. My guess is that it’s due to the need to allocate space as needed. The memory allocation itself will consume CPU cycles. The default StringBuilder constructor will allowcate 16 bytes initially. Thereafter, it will allocate two times the current capacity whenever needed.

String Size = 100

When the concatenated value is 100 characters, the all three methods perform very similarly up to three concatenations, then StringBuilder/Pre-allocated pulls ahead at 4 concatenations.

Concatenated String Size = 1000

At 1000 characters, things begine a little bit more interesting: StringBuilder/Pre-allocated is faster in all cases (although the difference is very small until about 6 concatenations). Since it may not be always possible or practical to know the final string size ahead of time, for this graph, I also added two more series to show what happens if you over-estimate or under-estimate the final capacity. As expected, there is a performance penalty for both. The more inaccurate your estimated capacity is, the higher of a performance penalty you will get.

What about String.Concat?

Lars Wilhelmsen asked “What about string.Concat?” According to my research, string.Concat is basically identical to “+” used on a single line.

This:

string s = "a" + class="str">"b" + "c";

Is the same (same generated IL) as this:

string s = string.Concat( class="str">"a", "b", "c");

But not this:

string s = "a";
s = s + "b";
s = s + "c";

Remember, the “+” must be on the same logical line, otherwise, the compiler will convert each line into a separate string.Concat operation, resulting in slower performance.

AJ has written a post detailing string.Concat here. Thanks, AJ, for pointing it out.

And String.Format?

Flyswat wanted to know about string.Format. I did some quick benchmark code again. The string.Format code below took 58 milliseconds to run 100,000 iterations:

string s = string.Format( class="str">"Value: {0}", strVal);

While this code, using “+” concatenation, only took 9 milliseconds (also 100,000 iterations):

string s = "Value: " + strVal;

According to the above numbers, string.Format is significantly slower than “+” concatenations. The difference in speed is similar between s.AppendFormat(“Value: {0}”, strVal) and s.Append(“Value: ” + strVal). I have used String.Format a lot in my code and I have not thought about this performance penalty. It does make sense. String.Format (or StringBuilder.AppendFormat) has to scan the string looking for format specifiers… that takes time. String.Format is very useful to make the code easier to read or when you actually need to format numbers. Even with this new data, I will not neccessarily shy away from using string.Format. I will however definitely be much more observant when using it, especially when used inside a loop or performance critical code path.

Conclusions

The new benchmarks do point to StringBuilder/Pre-allocated as the fastest method regardless of number of concatenations, when the concatenated string value is large (1000 characters).

With that in mind, here are my slightly modified rules of thumbs for string concatenation. Remember, “rules of thumb” are short statements to provide general princicles, and may not be accurate for every single situation. For performance criticial code, you should consider running some benchmarks/profiling yourself.

For 1-4 dynamic concatenations, use traditional “+” concatenation.

For 5 or more dynamic concatenations, use StringBuilder.

When using StringBuilder, try to provide the starting capacity as close to the final string size as possible.

When building a big string from several string literals, use either the @ string literal or the + operator.

Source Code for Benchmarks

Here are my top 11 tips and tricks for getting things done faster with the Visual Studio 2005 IDE (without using third-party add-ins or upgrading hardware… that’s another article). Yes, some of these tips and tricks may fall into the "obvious" category, but I think they are worth repeating. I continue to see too many .NET developers not taking advantage of even the basic time-saving techniques.

I work mostly with C# so some of these tips may not apply to, or work differently with other Visual Studio languages such as Visual Basic.NET.

(1) Express Yourself with Regular Expressions

Regular Expressions is a powerful and portable text search/replace/transformation language. Learning basic Regular Expressions will immediately make you a more productive developer/power user. Regular Expressions is supported in Visual Studio’s various Search/Replace dialogs. Any Regular Expressions skill you learn will also be useful in numerous other applications and settings: other text editors, unix shell/egrep, PowerShell, input validation, and Google search (heh, just kidding on that last item).

You can also use Regular Expressions with macros and automation via the Regex class.

Here’s an example of how you can save time with Regular Expressions in Visual Studio. Say, you just wrote and tested a SQL in a Query Tool and you want to turn it into a string variable in your C# class? Here’s how:

First, paste the SQL text into the editor. Make sure to remove any unwanted indentation on the left side of the text (SHIFT-Tab):

Then hit CTRL+H to bring up the Find and Replace Dialog and fill it out like this:

Note: For VB.NET, in the “Find and Replace Dialog Window”, change the value in “Replace With” box: from {[ + “\1″ ]}… to {[ & “\1″ _ ]}. Thanks to berkx for this info.

Explanation? Basically, the "Find what" expression above matches the content of each line and give it a numbered "tag". The "Replace with" expression then replaces each line with the first tagged value (\1), wrapped around in + " ". Click the fly-out (triangle) button next to each box to display a cheat-sheet of frequently used expressions. Oh, and don’t worry about the "+" string concatenations in the example, the compiler knows to optimize that syntax.

Once you’ve created a few Search/Replace expressions like the above, create macros out of them and assign to shortcuts.

Here are some of the Regex transformations I use most often when writing code:

Surrounds each line with (example above).

Transform a list of values separated by newlines into a coma-delimited list (used in array initializers or SQL where clause).

(4) Use Code Snippets

Save time typing repetitive code by using Code Snippets. There are two types of Snippets in Visual Studio 2005: Expansion and SurroundsWith. To use Expansion Snippets, type the Snippet shortcut (not to be confused with keyboard shortcuts), and press Tab twice.

For example, the "for" Snippet is an Expansion Snippet. To use it, type "for"…

Then press Tab, Tab:

I find SurroundsWith Snippets more useful though. An example SurroundsWith Snippet is "#region". First, select a block of code:

Then, type CTRL+K, CTRL+S and "#re":

Then hit Enter:

Here are my favorite Snippets:

#region: Regions is a great way to organize your code.

using: If you create an IDisposable object, you should use the "using" pattern. In addition to the basic "using" Snippet, I also created several variations for TransactionScope, and IDataReader.

(5) State Your Preferences

Find yourself constantly switching to the Design view every time you create/open an ASPX page? Cannot locate your current file in the Solution Explorer? Easy… just change the right settings and never think about it again.

(6) "Attach to Process" to Start Debugging ASP.NET

Most ASP.NET developers use the standard F5 (Debug/Start Debugging) to start debugging from Visual Studio. However, there is a much faster way to start debugging if you already have an instance of your web application running. Just attach to it instead:

Choose Debug/Attach to Process.

Select the "aspnet_wp.exe" process and choose Attach.

Or, for keyboarders:

ALT+D, P, "as", Enter.

Debugging this way is faster because you skip the often-lengthy compilation step, and you don’t have to navigate from the start page to the actual page that you want to debug.

(7) Stop Conditionally (Conditional Breakpoints)

How often have you found yourself repeatedly stepping through a loop while debugging, waiting to get to a specific loop value (because the bug only occurs with that specific value)? With Conditional Breakpoints, you don’t have to do that. Just set a Breakpoint Condition.

Set the Breakpoint. Right click on the Breakpoint indicator (red circle), and choose Condition:

Set the condition (any valid C# expression):

Another debugging productivity trick I use is to override ToString() to return a useful summary of your objects. The Debugger uses the value returned by ToString in various Debug windows such as Watch Window. You can also use the DebuggerDisplay attribute.

(8) Employ Task List Tokens

Use Task List tokens such as TODO and HACK to quickly mark incomplete code or code that requires further attention. This allows you to keep flowing and skip over the details, but at the same time ensures that you will not forget to go back and finish up.

A shortcoming with Visual Studio 2005’s Task List is that it only shows the items in the current file. You can get around this by using the Find in Files feature and search for "// TODO".

(9) Go Directly to Any File with the Find Combo Box

This is the Find dropdown that is on the Standard Toolbar, not the Find dialog. Use the shortcut CTRL+D to activate the Find dropdown in normal mode. Use CTRL+/ to activate the Find dropdown in command mode (with ">" prepended… this doesn’t work sometimes for me).

To quickly go to a file, type CTRL+D, >open <start of file name>. Intellisense works here just like in the Command Window. "of" (short for "open file") can be used instead of open. Compare this with opening Solution Explorer, expand the correct folder/project, and visually hunt for the file you need.

With the Find Combo, you can also execute commands, macros, find text, etc. More info:

Additional reading

Even in today’s environment, when the typical amount of RAM on each server is in the gigabytes, it’s still wise to pay attention to memory usage. As a developer or architect, you need to be aware of the trade-offs between eager instantiation and lazy instantiation. Yes, it’s rather pointless to consider an Int16 versus an Int32 for a variable if it’s just going to be created and used a few times in the lifetime of your application. However, if that same variable is instantiated thousands of times or more, then the potential improvement in either memory usage or performance (whichever is more important to you) is definitely worth a look.

Eager/lazy instantiation also applies to classes, singletons, etc. The principles and potential advantages/disadvantages are similar. For this article, I am only discussing the instantiation of class members.

CPU Cycles vs. Memory Usage

Eager vs. lazy instantiation is the classic performance/memory trade-off. With eager instantiation, you gain some performance improvement at the cost of system memory. Exactly what kind of performance/memory trade-off are we talking about? The answer depends mostly on the objects themselves:

How many instances of the parent object do you need?

What is the memory footprint of the member object?

How much time does it take to instantiate the member object?

How often will the parent object/member object be accessed?

Calculating the Memory Footprint of an Object

According to my own experiments (using DevPartner Studio and .NET Memory Profiler), each reference-type object (class) has a minimum memory footprint of 12 bytes. To calculate the total memory footprint of each reference-type object, add up any other memory used by members in the object. To get the exact memory footprint, you also need to take into consideration “boundaries” but for our purpose that’s probably not important.

The memory foot-print of an object can be closely approximated using the following table (from MSDN Magazine):

Type

Managed Size in Bytes

System.Boolean

1

System.Byte

1

System.Char

2

System.Decimal

16

System.Double

8

System.Single

4

System.Int16

2

System.Int32

4

System.Int64

8

System.SByte

1

System.UInt16

2

System.UInt32

4

System.UInt64

8

Using the example Customer class above, let’s say that each Address object take up 1 KByte, and my application frequently needs to instantiate up to 10,000 Customer objects. Just by creating 10,000 Customer objects, we would need about 10 Megabytes of memory. Now let’s say that the HomeAddress member is only needed when the user drills down into the details of a Customer, and we are looking at a potential saving of 10 Megabytes of memory by using lazy instantiation on HomeAddress.

Memory Usage Can Also Impact Performance

Another important consideration with .NET managed code is garbage collection. In .NET managed code, memory usage has a hidden impact on performance in terms of the work the garbage collector has to perform to recover memory. The more memory you allocate and throw away, the more CPU cycles the garbage collector has to go through.

Recommendations

Pay closer attention to classes that get instantiated multiple times, such as Orders, OrderItems, etc.

For light-weight objects, or if you are not sure, use lazy instantiation.

If a member object is only used some of the times, use lazy instantiation.

Ok, so System.Transactions is not new to many .NET developers but it’s new to me. We have just started to research transaction management in my current .NET 2.0 project at work and System.Transactions is looking beautiful. It gives us exactly what we need without the overhead of the old EnterpriseServices model (registering with COM+, having a strong name key, etc.) or the high maintenance of manual transaction management.

System.Transactions is more light-weight compared to EnterpriseServices. The programming model is relatively simple. You use the TransactionScope class to wrap your code inside a transaction. TransactionScope can be nested and can be assigned different transaction options such as Required or RequiresNew, similar to the various transaction attributes for EnterpriseServices.

using (TransactionScope scope = new TransactionScope())
{
// do some work here (like executing a SQL, calling a method, etc.)// The Complete method commits the transaction. If an exception has been thrown,// Complete is not called and the transaction is rolled back.
scope.Complete();
}

In my brief testing with Enterprise Library 2.0 and an Oracle database via Oracle Data Provider, I found that System.Transactions always enlist my transactions in MSDTC (Microsoft Distributed Transaction Coordinator). I am sure there is some overhead associated with this. I will do some more performance test later to find out exactly what the overhead is. I was hoping that for a transaction involing a single database/connection string, that MSDTC would not be needed. But further research indicated that the non-MSDTC/light-weight transaction only works with SQL Server 2005.

If your transaction management needs extend beyond databases, you can even write your own resource manages so that operations such as copying a file can be wrapped inside a transaction as well. Look into the IEnlistmentNotification interface.

Here are some good articles about System.Transactions for your further reading:

How often have you been told to use StringBuilder to concatenate strings in .NET? My guess is often enough. Here is something you may not know about string concatenation: StringBuilder is not always faster. There are already many articles out there that explain the why’s, I am not going to do that here. But I do have some test data for you.

When concatenating three values or less, traditional concatenation is faster (by a very small margin)

The above data suggests that StringBuilder only starts to work faster once the number of concatenations exceed 3.

Building strings from literals

When building a large string from several string literals (such as building a SQL block, or a client side javascript block), use neither traditional concatenation nor StringBuilder. Instead, choose one of the methods below:

For me, Co-op is a good idea but for now I will stick with just regular Google, at least for .NET related searches. I gave SearchDotNet.com a try and was initially underwhelmed my the number of matches. For example, searching for “EntryAssembly” using the DotNetSearch engine above yielded two pages of matches. Regular Google returns 387 pages.

We all know that it’s a good idea to test our web pages in all popular browsers (to me that’s the various current versions of Internet Explorer and Firefox). It’s also a good idea to back up your data frequently, to listen to your elders, to not take a bath right after dinner, etc. Ok, so I admit I didn’t test my latest WordPress theme in IE6. While browsing the web on a friend’s PC, I discovered that my blog did not render correctly in IE6. It was broken in a major way. The right side bar completely disappears. Ouch!

I needed a way to test my site in Internet Explorer 6 at home, and since I have upgraded all of my PC’s at home to IE7, it seems like it’s a good time to give “virtual appliances” a try.

It took me about an hour to download the Internet Explorer 6 Application Compatibility VPC Image, install it, and have the virtual machine up and running. It helped that I already had Virtual Server installed. Yes Virtual Server works with Virtual PC disk images just fine. The current IE6 image expires on 4/1/2007 but I am sure Microsoft will replace it with another one when the time arrives. There is a blog entry on IEBlog about the image here.

Now I can reproduce the problem on my PC using IE6. That’s going to be the easy part I am afraid.

Update (2/8/2007): I fixed the IE6 problem. Apparently I had some sort of error in my sidebar.php file which messed up the HTML code, causing problems with IE6.

It’s been a while since my last post… I have been very busy with wrapping the latest development project at work and I also took a 3-week long vacation to Vietnam in December! That was nice. I am still having post-vacation depression syndrome. When I have more time I will write more about the trip to Vietnam and maybe post some pictures.

Anyway, this post is about .NET memory leaks. If you suspect a memory leak in your .NET managed code, I recommend downloading a tool called .NET Memory Profiler. In my last project, we had a huge managed memory leak in our app due to the incorrect use of static events. This tool was a life saver because it helped us track down the memory leak.