How to measure Web Service’s performance?
There are two aspects to measuring and evaluating the performance of an application composed of one or more Web services.
- The first is the throughput of the Web service itself. This is its ability to accept a request and provide a response in accordance with required performance parameters. On a larger scale, it’s also the ability to actually have a transaction throughput that the component was designed to meet.
- The second aspect is the ability to evaluate the performance of the application in the aggregate, including the Web service. This includes not only the ability of the Web service to respond, but also how that response is coordinated with the responsiveness of the application as a whole. While the focus may be specifically on the performance of the Web service component, it must be analyzed within the context of the entire application.
To accomplish this, it’s necessary to measure the performance of all of the application components simultaneously, during the same testing run, and correlate those disparate measurements into an integrated view. While the Web service may appear to perform acceptably within its own context, resource or processing issues, synchronization problems, and networking, or data throughput, bottlenecks may prevent it from reaching its potential.
Unit Testing During Development
Unit testing a Web service presents the first significant challenge. As a practical matter, it requires an external stimulus to initiate execution, so it isn’t simple to call the service as one would a DLL or link it in as one would a library. Fortunately, using the Web services wizard in Visual Studio .NET has the side effect of creating a Web page front end for functional testing purposes, and it works well enough to initiate unit testing also.
Otherwise, one would have to write your own call method into the service.
Unit testing should cover both functional and performance testing. Functional testing involves exercising the operations which compose the service, to ensure that they behave as specified. Whether one employ an automated test management system or conduct these unit tests manually, keeping track of code coverage is important to determine what code is tested and how much has been tested. Many developers already do this, and while doing so with Web services opens certain challenges, the process is largely familiar.
The goal of performance testing is to identify slow code and potential bottlenecks. For developers with experience in monolithic or tightly coupled applications, this is often simply a matter of noting that the application doesn’t perform as expected, isolating the component responsible, and fine-tuning the code. It’s not quite like that when building a loosely coupled application with Web services.
However, profiling a .NET Web service is a necessary part of the development process. Since we’re not looking at performance or scalability testing of the entire application at this point, one can initiate profiling early in the development cycle.
At a minimum, profiling should collect two types of information – execution time and number of times executed.
- The reason for the first is readily apparent – so that you can quickly identify parts of the code that seemingly execute more slowly than others. It’s not necessarily indicative of poorly performing code because it may just be performing a computationally intensive operation that can’t be improved upon. However, information on the performance of your code justifies a closer look.
- The number of times executed can also be indicative of poorly performing code, but in a different sense. A single line or method may execute in an acceptable amount of time, but may be inefficient in the sense that a single call to that operation does too little work for too much overhead. The trick is to find the optimum amount of data that can be processed most efficiently.
Analyzing Performance and Diagnosing Issues
Profiling a .NET Web service frequently requires looking at both managed and unmanaged code simultaneously. This may be because all but the most trivial calls into native code must undergo a mode transition. The mode transition, which is the physical process of moving data between the managed and unmanaged modes of operation, typically requires about two dozen instructions. The second cost is marshalling the data to move across the boundary. Marshalling is computationally expensive, and the more data you move back and forth, the more expensive it becomes.
Alternatively, within the Microsoft model Web services can also be unmanaged. Existing or new COM components can be used to implement the business facade, business logic, and data access layers.
Therefore, it is possible that we are making unmanaged calls from the .NET Web service, either because it is used as a gateway to call COM objects, or are making platform calls, or are using prepackaged native components. Profiling both managed and unmanaged calls together gives a comprehensive view of the Web service, and most important a view of the performance cost of mode transitions.
The granularity of the profiling should be at least to the method level, and preferably to the individual line of code. At the method level, one can quickly get a view of what operations the code is spending most of its time performing.
In addition to obtaining the execution time and number of calls, it should also be able to analyze the code in several different views of performance, including percent of time in method and percent of time in children. Walking the call stack is an excellent way of determining what resources, .NET services, and OS services your Web service is using, and how expensive those services are.