Code profilers are an often-underrated tool when in fact they can be one of the most powerful tools a developer can possess. Profilers sift through the code and record thousands of data points that are then turned into useful information for the developer. For example, code profilers can show you which method took the most time to execute within the entire application, what variable consumed the most memory, and which operations were the most costly. When developers get into the habit of running a profiler on their code, they will be able to find and correct many performance problems that might not otherwise be immediately obvious.
Visual Studio 2005 has several editions that come with a built-in code performance analyzer. You can get to this performance analyzer by launching the Performance Wizard from the Performance Tools menu under the Tools menu.
To see the Performance Wizard in action, first create some code that does something that is quite obviously a performance problem. The code in Listing 16.2 represents a quick console application that will definitely cause some blatant results in a code profiler.
Listing 16.2. Inefficient Use of String Concatenation and Looping
You have already seen that string concatenation within a loop can cause a massive waste of space on the heap. After running the profiler, you will see exactly how much space is wasted. To launch the profiler, first build the application and then launch the Performance Wizard from the Performance Tools menu. At the prompt, select the default project for the target (the project you created for this sample) and choose the Sampling method of analysis. This will create a new performance session. To run the analysis and get results, click the Launch button in the Performance Explorer panel that appeared after creating the session.
When the analysis is complete, a new file with the extension .vsp will be added to your solution. This file is a report that contains several tabs.
Click on the Call Tree tab. From this tab, shown in Figure 16.2, you can see that string concatenation accounted for roughly 96% of the work done by the application.
Figure 16.2. The Call Tree tab of a performance report.
Next, click on the Allocation tab and you will see a list of the bytes allocated for every single type used in the application, as shown in Figure 16.3. Something really troubling in this figure is that the results of string concatenation were responsible for 99.93% of all allocation within the application; 930MB worth. Even though there were only 10,000 strings in the list, 40,002 instances of strings were created as a result of string concatenation.
Figure 16.3. The Allocation tab of a performance report.
Finally, click the Objects Lifetime tab of the report. This shows you how long objects resided in memory categorized by what the garbage collector refers to as generations. A generation is a group of objects with similar uncollected lifetimes. When the garbage collector does a pass through the heap looking for objects to dispose, Generation 0 objects will be disposed immediately. Objects that could not be disposed will be moved to Generation 1 to be disposed later. Finally, if an object cannot be disposed from within Generation 1, it is moved to Generation 2. In order to keep the performance of the garbage collector at a maximum, you want to aim to keep as many of your objects as possible in Generation 0. Figure 16.4 shows that roughly 44,000 strings were Generation 0 objects, 159 lasted long enough to make it into Generation 2, and 5,633 objects were considered "large objects" by the garbage collector.
Figure 16.4. The Objects Lifetime tab of a performance report.
In addition to performance profiling, you can also use another tool provided by Microsoft that actually validates your code against more than 200 rules of design dictated by the .NET Framework design guidelines. This tool is called FxCop and you can download it from Microsoft. Figure 16.5 shows a screenshot of FxCop after analyzing the preceding code for failures to comply with standard .NET Framework application design guidelines.
Figure 16.5. FxCop in action.
Using FxCop and the Visual Studio Performance Wizard, you can get a blueprint of how your application is performing and how well it conforms to accepted .NET Framework design guidelines and best practice rules. Both of these tools should be used regularly by developers to maximize the efficiency and design guideline conformance of their applications.