Microsoft's .NET Framework provides developers with the tools and the infrastructure for easy development and deployment of Web services. But this new technology won't change a basic fact about service applications: their performance and reliability remain the number-one criterion for successful business implementation. A bug that causes the crash of a client-side application will affect only one user, or at most a couple more, but a bug on the server side can leave thousands of users without the business information they require at a given time.
Fortunately, unexpected crashes, poor performance, and corrupted data can be prevented by doing runtime analysis early in the development cycle. Runtime analysis is one of the key activities for building high-quality .NET Web service applications -- that is, applications that are reliable (no crashes, peculiar error messages, or false results), fast, and thoroughly tested. Rational PurifyPlus is a set of three tools that can help developers achieve these goals. Rational Purify eliminates bugs that are difficult to find, Rational Quantify pinpoints performance bottlenecks, and Rational PureCoverage reveals untested code.
In this article, we'll show you how to use the Rational PurifyPlus tools to do runtime analysis of ASP.NET Web service applications. In particular, we'll discuss Microsoft .NET server-side execution and give step-by-step instructions on how to activate server-side profiling with PurifyPlus. We'll show examples of how to invoke PureAPI and test a Web service. First, though, we'll say a little bit more about runtime analysis with PurifyPlus.
Key Problems Addressed by Runtime Analysis with PurifyPlus
Runtime analysis can help developers detect and resolve the memory and performance issues that are very difficult to fix if the Web service application is already deployed and running. Here are some of the key problems addressed by runtime analysis:
Unstable and unreliable software -- The PurifyPlus tools record and pinpoint the weak spots in the program under development, allowing developers to fix problems that cause the software to perform poorly and unreliably, with minimum effort and time invested.
Inability to pinpoint the root causes of reliability and performance problems -- The PurifyPlus tools automatically locate the root causes of memory errors and performance and memory bottlenecks in the source code of the tested application without modifying the code.
Inability to measure software quality -- Reports created by the PurifyPlus tools provide sufficient information for evaluating the level of software quality achieved throughout the development process.
Inadequate testing procedures -- The PurifyPlus tools reveal untested and unused code and measure the quality of testing methods.
Another way to say this is that the PurifyPlus tools automate the following software development activities:
- pinpointing and tracking difficult-to-find bugs
- pinpointing performance and memory bottlenecks
- revealing untested and unused code
- measuring the quality of testing methods
- creating extensive documentation about the tests run
- manipulating reports (comparing and merging reports, for example) in order to measure improvements in the project development
- measuring the quality of the developed application
More information about runtime analysis with Rational PurifyPlus can be found in the article "Runtime Analysis in Visual Studio .NET with Rational PurifyPlus."
A Short Introduction to Microsoft .NET Server-Side Execution
Microsoft .NET server-side code hosting is implemented as an extension to IIS (Internet Information Services). IIS is a Windows service running in the context of Windows Service Manager (services.exe). Being a service, IIS is started before any user application and remains active until the system gets rebooted or IIS gets shut down from the Windows Management Console. In the .NET Framework, an additional component is employed by IIS for hosting managed code components -- aspnet_wp.exe. This component is shipped with the .NET Framework and is started by IIS when the first .NET module execution is requested.
Figure 1 shows how different server components interact with each other and with PurifyPlus when you're running managed code (.NET applications built on the Common Language Runtime or CLR).
|
| Figure 1: Interactions among server components and PurifyPlus when managed code is run |
You should keep these facts in mind when dealing with server-side execution and profiling:
Services (including IIS) run in the
SYSTEMsecurity context by default. (This can be changed via the Management Console.)Services use the service-specific WinStation (
Service-0x0-3e7$). This prevents services from creating windows and getting keyboard or mouse input. All processes created by a service automatically inherit this WinStation. You can get a service to employ a user-oriented WinStation calledWinsta0by enabling IIS to interact with the desktop.The .NET managed-code host (
aspnet_wp) is configured to run in a special security context --ASPNET_WP. User privileges in this context are limited compared with theSYSTEMcontext. For one thing, this context preventsaspnet_wpfrom usingWinsta0even if you enable IIS to interact with the desktop. TheASPNET_WPsecurity context can be changed by editing theprocessModelsection of themachine.configfile, but this isn't recommended because it may open IIS to attack.All services inherit system environment variables from the Windows Service Manager. This means you have to reboot the operating system to update environment settings for a service.
Activating Server-Side Profiling with PurifyPlus
To activate server-side profiling of an ASP.NET Web service application with PurifyPlus, you must have the following installed:
- Microsoft .NET Framework V1.0.3617 or later
- PurifyPlus build 3234 or later
In addition, you must be logged in as a member of the Administrators group. Here are the steps to activate profiling:
- Set the environment variables. From the Control Panel, choose System Settings > System > Advanced > Environment Variables and add the following values to the system environment:
COR_PROFILER={679367E3-FC39-11D3-8A11-00105A2A1490}(Note that this class ID for the current PurifyPlus CorProfiler class may change in future versions of PurifyPlus.)COR_ENABLE_PROFILING=1PURE_MONITOR_ENABLE=mode, where mode isPurifyto enable memory profiling,Quantifyto enable performance profiling,Coverageto enable code coverage analysis, or nothing to disable profiling (Note that these mode settings are case-sensitive.)- Add the Purify, Quantify, and PureCoverage product directory to the system path.
- From the Control Panel, choose Administrative Tools > Computer Management > Services and Applications > Services and change the IIS Admin Service startup mode to manual.
- Reboot the system if necessary.
- Start the PurifyPlus tool (Quantify, Purify, or PureCoverage) corresponding to the PURE_MONITOR_ENABLE value.
- Start the IIS Admin Service.
- Start the World Wide Web Publishing Service.
- Navigate to the page hosting the server-side IL code.
- When the run for collecting the profiling and coverage data is finished, close the Internet Explorer browser (the client) and the IIS Admin Service (the server).
The profiling should begin as soon as the first assembly gets loaded.
Interpreting the Profiling Results
The PurifyPlus tools collect profiling data during run time and display the results in various views upon closing the tested application. If the tool selected for profiling was Rational Purify, you'll be able to analyze the execution flow, which pinpoints the methods where most of the memory was allocated during the run or between snapshots.
Keep these points about server-side code profiling, in contrast with the standard client-side profiling, in mind as you examine the results:
- All server-side code runs in the same application context (as of today,
aspnet_wp.exe). - Once started, server-side code continues to run until the ASP.NET Framework decides to terminate this application domain to make room for more processes or the IIS server is restarted.
- All server-side code from the same session currently goes to the same data set.
To make analyzing the data collected for the different application domains easier, we suggest you use the PureAPI functions to collect performance- and memory-profiling data for specific portions of the Web service application. You can also specify the section of the Web service for profiling from within the GUI of the PurifyPlus tools, but using the PureAPI functions gives better synchronization and is the only option for automated tests.
Invoking the PureAPI Functions
Here we'll describe some PureAPI invocation techniques specific to server-side IL code. The basics of PureAPI invocation are the same as for any other code. You should import the PureAPI assembly, resolve the Rational namespace, and start calling appropriate methods of the PureAPI class, preferably using the "code-behind HTML" approach as illustrated in Listings 1 and 2 below. All you have to do is specify your code-behind assembly in the <%@ Page %> directive in the ASPX file, as shown in Listing 1, and add the PureAPI reference to your assembly list.
<%@ Page language="c#" Codebehind="PureAPITest.aspx.cs" AutoEventWireup="false" Inherits="PureAPIFromWebApp.PureAPITest" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <title>WebForm1</title> <meta name="GENERATOR" Content="Microsoft Visual Studio 7.0"> <meta name="CODE_LANGUAGE" Content="C#"> <meta name="vs_defaultClientScript" content="JavaScript"> <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5"> </HEAD> <body MS_POSITIONING="GridLayout"> <form id="Form1" method="post" runat="server"> <asp:Label id="Label1" style="Z-INDEX: 101; LEFT: 41px; POSITION: absolute; TOP: 24px" runat="server" Width="357px" Height="32px" Font-Bold="True" Font-Size="Large" ForeColor="Blue">PureAPI Test Page</asp:Label> <asp:Label id="LabelIsRunning" style="Z-INDEX: 102; LEFT: 45px; POSITION: absolute; TOP: 81px" runat="server" Width="358px" Height="20px"></asp:Label> <asp:TextBox id="TextBoxAnnotation" style="Z-INDEX: 103; LEFT: 44px; POSITION: absolute; TOP: 132px" runat="server" Width="260px" Height="23px"></asp:TextBox> <asp:Button id="ButtonAddAnnotation" style="Z-INDEX: 104; LEFT:350px; POSITION: absolute; TOP: 133px" runat="server" Width="100px" Text="Add Annotation"></asp:Button> <asp:Button id="ButtonSnapshot" style="Z-INDEX: 105; LEFT: 47px; POSITION: absolute; TOP: 211px" runat="server" Width="103px" Height="26px" Text="Snapshot"></asp:Button> </form> </body> </HTML> |
Listing 1: PureAPI invocation example -- ASPX file
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using Rational;
namespace PureAPIFromWebApp
{
/// <summary>
/// Summary description for WebForm1.
/// </summary>
public class PureAPITest : System.Web.UI.Page
{
protected System.Web.UI.WebControls.Label Label1;
protected System.Web.UI.WebControls.Label LabelIsRunning;
protected System.Web.UI.WebControls.TextBox
TextBoxAnnotation;
protected System.Web.UI.WebControls.Button
ButtonAddAnnotation;
protected System.Web.UI.WebControls.Button ButtonSnapshot;
private void Page_Load(object sender, System.EventArgs e)
{
// Put user code to initialize the page here.
LabelIsRunning.Text = "PureAPI is ";
if (PureAPI.IsRunning() == 0)
LabelIsRunning.Text += "not ";
LabelIsRunning.Text += " running";
}
#region Web Form Designer generated code
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: This call is required by the ASP.NET Web
// Form Designer.
//
InitializeComponent();
base.OnInit(e);
}
/// <summary>
/// Required method for Designer support -- do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.ButtonAddAnnotation.Click += new
System.EventHandler(this.ButtonAddAnnotation_Click);
this.ButtonSnapshot.Click += new
System.EventHandler(this.ButtonSnapshot_Click);
this.Load += new System.EventHandler(this.Page_Load);
}
#endregion
private void ButtonAddAnnotation_Click(object sender,
System.EventArgs e)
{
PureAPI.AddAnnotation(TextBoxAnnotation.Text);
}
private void ButtonSnapshot_Click(object sender,
System.EventArgs e)
{
PureAPI.SaveData();
}
}
} |
Listing 2: PureAPI invocation example -- code-behind PureAPIATest.aspx.cs file
If, for whatever reason, you have to use a plain-text server-side script, you'll need the <%@ Assembly %> directive in order to resolve the PureAPI interface:
<%@ Assembly Name=PureAPI-assembly-reference %>
where PureAPI-assembly-reference is PureAPI.dll-path\"PureAPI.dll"
Listing 3 below is a Web service sample illustrating PureAPI invocation from the server-side code.
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Web;
using System.Web.Services;
using Rational;
namespace PureWSTestService
{
/// <summary>
/// Summary description for Service1.
/// </summary>
public class TestService : System.Web.Services.WebService
{
public TestService()
{
// CODEGEN: This call is required by the ASP.NET Web
// Services Designer
InitializeComponent();
}
#region Component Designer generated code
// Required by the Web Services Designer
private IContainer components = null;
/// <summary>
/// Required method for Designer support -- do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if (disposing && components != null)
{
components.Dispose();
}
base.Dispose(disposing);
}
#endregion
[WebMethod]
public string IsPurifyPlusRunning()
{
string rVal = "PureAPI is ";
if (PureAPI.IsRunning() == 0)
rVal += "not ";
rVal += " running";
return rVal;
}
[WebMethod]
public void AddAnnotation(string annotation)
{
PureAPI.AddAnnotation(annotation);
return;
}
[WebMethod]
public void SaveData()
{
PureAPI.SaveData();
return;
}
}
} |
Listing 3: PureAPI invocation from the server-side code
You can download the file Src.zip, containing the minimum code necessary to build the sample Web service.
- Use
PureWSTestService.asmxandPureWSTestService.asmx.csto build the sample service. - Use
PureWSTestForm.aspxandPureWSTestForm.aspx.csto build a Web form using the sample service.
Note that you'll have to reference PureAPI.DLL in your PurifyPlus product directory.
High-quality .NET Web service applications are reliable, fast, and thoroughly tested. The Rational PurifyPlus package offers the tools you need in order to assure application quality. With Purify, Quantify, and PureCoverage, you can pinpoint and analyze performance issues, identify memory usage problems, and find untested code. This article has shown you how to do server-side profiling with these tools. Try it out for yourself and watch your application quality improve.
References and Other Resources
- "Runtime Analysis in Visual Studio .NET with Rational PurifyPlus" by Goran Begic (Rational Developer Network)
- Microsoft .NET Tool Developers Guide: "Profiling" (found in the .NET Framework SDK, in the file
%VS.NET_HOME%\FrameworkSDK\Tool Developers Guide\docs\Profiler.doc) - "Debugging and Profiling Applications" (Microsoft MSDN Library)
- "Inside the .NET Framework" (Microsoft MSDN Library)
- PurifyPlus online help
- Professional ASP.NET 1.0, Special Edition by Alex Homer et al. (Wrox Press, 2002)
Victor L. Havin is a software engineer in the development solutions business unit (DSBU) at IBM Rational Software. He's been working on performance tuning and runtime error detection tools since joining Rational in 1997. When not working on advanced software projects, Victor enjoys skiing and rock climbing. Victor can be reached by e-mail.
Comments (Undergoing maintenance)





