Archive for the '.NET' Category
Once slow code has been identified, the next step is to address those issues. One popular technique for addressing how data is passed between the application and the Web service is to carefully monitor and optimize the amount of data transmitted in each SOAP call.
In this circumstance, one change that can be considered is whether the code should be “chatty” or “chunky.” As the names imply, chatty calls are those that occur often and pass little data, while chunky calls occur less frequently but do more work when they do occur.
While at first glance it might appear that large calls to the service are more efficient, that’s not necessarily true. A chatty interface passing less complex data more often may turn out to be less computationally expensive because its marshalling isn’t as complex.
How to determine whether or not one should be using chatty or chunky calls to the service? There’s no easy way that applies to all circumstances; it depends on the amount of data and frequency of calls. The best thing to do is to prototype both the type of interface and the performance profile. By investing a little time early in the development phase, one can ensure that the right performance choice has been made and not have to go back and make substantial changes after there is a working application.
That’s not to say that one might not have to go back and make adjustments to the calls once the application is done. For example, it may be found that in certain Web services features, chunky calls are more efficient because of the overall volume of calls. But prototyping the data and calls ahead of time gives a better ability to determine the optimum amount of data to exchange with the Web services in individual transactions.
Another common problem is that certain .NET services can be computationally expensive. At first glance it may appear that we have little control over what the .NET Framework does. However, the framework is rich in features, and there are often multiple ways of obtaining the services that are in need. Alternatively, the framework calls that are being used may be doing more work than actually needed. We won’t know any of this unless we have complete profiling information on child behavior from our own methods.
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.
1.Web Services Implementation Considerations
1.1 Approaches to caching
Caching is a great way to improve Web service performance. By reducing the average request time and easing server load, caching also helps scalability. Frequently used data applicable to all users or SOAP response output can be cached. Application data can be cached by using ASP.NET caching features. SOAP output can be cached by either using the ASP.NET output cache or by employing perimeter caching. When designing a caching strategy for a Web service, consider the following guidelines:
- Use output caching with the CacheDuration property
- Consider providing cache related information to clients
- Consider perimeter caching
Use Output Caching with the CacheDuration Property
If portions of the output are static or nearly static use ASP.NET output caching, ASP.NET output caching must be used with Web services, by configuring the CacheDuration property of the WebMethod attribute. The following code shows an example where the cache duration is set to 30 seconds
[WebMethod(CacheDuration=30)]
public string SomeMethod() { … }
Consider Providing Cache Related Information to Clients
The clients of the Web service can also implement custom caching solution which caches the response from the web service. If the clients of the web service are expected to cache the response, consider providing cache expiration related information to the clients so that they send new requests to the Web service only after their cached data has expired. Additional field can be added in the Web service response that specifies the cache expiration time.
Consider Perimeter Caching
If the output from the web service changes infrequently, hardware or software (ISA firewall) to cache the response at the perimeter network can be used. Perimeter caching will respond before the request even reaches the web server reducing the amount of requests that need to be serviced by the web servers.
1.2 Serialization Considerations
Serialization is an important issue from the web services’ performance point of view since web services uses XML in SOAP messages.
1.2 .1 Reduce Serialization with XmlIgnore
To limit which fields exposed by an object are serialized when the object is passed to or from a Web method and to reduce the amount of data sent over the wire, the XmlIgnore attribute should be used as shown below. The XmlSerializer class ignores any field annotated with this attribute. Please note that XmlIgnore serializes only public members unlike the formatters derived from IFormatter interface.
// This is the class that will be serialized.
public class MyClass
{
// The str1 value will be serialized.
public string str1;
/* This field will be ignored when serialized–
unless it’s overridden. */
[XmlIgnoreAttribute]
public string str2;
}
1.2.2 Cache the XmlSerializer to Reduce Construction Overhead
Constructing an XmlSerializer is a costly operation. During construction it performs the following operations:
- It analyzes all of the types that are passed to it.
-
It generates some C# code to serialize the object and then launches the C# compiler to compile it. This overhead will be reduced in future versions of the .NET Framework.
To improve performance, it must be made sure that the reference to the XmlSerializer object is cached to avoid the construction overhead for each Web request.
For more information, see “XmlSerializer Architecture” in the November 2001 edition of MSDN magazine.
1.2.3 Reduce Round Trips
Reducing the round trips to the web service reduces the number of times the flow needs to cross serialization boundaries. This helps reduce the overall serialization cost incurred. Some of the design options which help reduce round trips are:
- Message based interaction for the web service must be considered.
-
Consider having a data façade for the out parameters which serve as a data contract with the clients. This helps sending all the relevant data to the clients by receiving one single request rather than sending the data on multiple requests.
1.2.4 Consider XML Compression
Compressing the XML payload sent over the wire helps reduce the network traffic significantly. Xml compression can be implemented by using one of the following
-
Implementing and using SOAPExtensions both on the server and client side for compression and decompression of both the request and the response.
-
Implementing a custom HttpModule on the server and overriding the proxy for the web service on the client side.
-
Using Http compression features available in IIS 5.0 and greater versions for compressing the response from the web service. You still need a decompression mechanism on the client.
1.3 Connection Performance Considerations
When Web services are called, TCP connections are pooled by default. If a connection is available from the pool it is used, otherwise a new connection is created up to a configurable limit. There is always a default unnamed connection pool. A connection group is a way to isolate a connection pool used by a given set of HTTP requests. Separate pools can be used by specifying a ConnectionGroupName when requests are made; otherwise the default connection pool is used. To use connections efficiently, it is necessary to set an appropriate number of connections, determine whether connections will be reused, and factor in security implications.
The following recommendations improve connection performance:
1. Configure maxconnections
2. Prioritize and allocate connections across discreet Web services
3. Use a single identity for outbound calls
4. Use PreAuthenticate with Basic authentication
1.3.1 Configure maxconnections
‘maxconnection’ limits the number of concurrent outbound calls. It does not apply to local requests. The default limit is 2 per Connection Group specified by the maxconnection attribute in machine.config or the application configuration file. For desktop applications calling Web services, 2 connections may be sufficient. For ASP.NET applications calling Web services, 2 is generally not enough.
Change the maxconnection attribute from 2 to 12 per CPU as a starting point:
<connectionManagement>
<add address=”*” maxconnection=”12″/>
</connectionManagement>
Note that 12 connections is an arbitrary number, but empirical evidence has shown that 12 connections are optimal for a variety of scenarios when ASP.NET is also limited to 12 concurrent requests. It is necessary to validate the appropriate number of connections for a given scenario.
1.3.2 Prioritize and Allocate Connections across Discreet Web Services
Enumerate and prioritize the Web services that need to be called. Allocate more connections to the critical Web services. Each Web service is specified using the address attribute as follows:
<connectionManagement>
<add address=”WebServiceA” maxconnection=”8″>
<add address=”WebServiceB” maxconnection=”4″>
</connectionManagement>
For example, if the application typically makes more requests to WebServiceA than WebServiceB, one can dedicate more connections, as seen in the example above.
1.3.3 Use a Single Identity for Outbound Calls
Single trusted identity must be used for making Web service calls wherever it is possible. This helps to limit the number of separate pools. While there is a need to create separate pools of connections for different discreet Web services, avoid creating pools per user. If there is a need to create pools per user, then specify a ConnectionGroupName when the Web service is called, but this will hurt performance and lead to a large number of pools.
The connection pool the call uses is not determined by the identity of the caller. The ConnectionGroupName determines which connection pool is used. If separate identities use the same ConnectionGroupName, they will use the same pool of connections. It may be neccessary to create separate pools of connections for different discreet Web services or if the identity of the original caller is flown.
If ASP.NET calls Web services that allow anonymous, connections from the default connection pool will be used. This is the default behavior unless a ConnectionGroupName is specified.
1.3.4 Use ‘PreAuthenticate’ with Basic Authentication
If Basic authentication is used, the proxy’s ‘PreAuthenticate’ property can be set to true or false. Set it to true to supply specific authentication credentials to cause a WWW-authenticate HTTP header to be passed with the Web request. This saves the Web server denying access on the request, and performing authentication on the subsequent retry request.
Note Pre-authentication only applies after the Web service successfully authenticates the first time. Pre-authentication has no impact on the first Web request.
There are a number of issues that must be considered to ensure that efficient Web services are created and a number of decisions that must be made at design time. The major considerations are summarized below:
Design Chunky Interfaces to Reduce Round Trips
Design chunky interfaces by exposing Web methods that allow your clients to perform single logical operations by calling a single Web method. Avoid exposing properties and instead provide methods that accept multiple parameters to reduce roundtrips.
Prefer Primitive Types for Web Service Parameters
There are two broad categories of parameter types that you can pass to Web services:
- Strongly typed: This includes .NET types such as double, int, DataSet and custom objects such as Employee, Person and so on. The advantage of using strongly typed parameters is that .NET automatically generates the schema for these types and validates the incoming values for you. Clients use the schema to construct appropriately formatted XML messages before sending them.
- Loosely typed: These parameters use the string type. Loosely typed parameters are beneficial for interoperability. For example, you can place an XML document containing a business document in the string parameter. The client needs to take care of serializing the data to XML before passing it to the Web service. The Web service implementation must develop custom validation code to validate the incoming message in addition to the de-serialization process. The advantages of loosely typed parameters include good interoperability support, avoiding certain versioning issues because even if the expected schema changes, the message is still wrapped in a single parameter.
Regardless of which encoding style you use, you should prefer simple primitive types like int, double, and string for Web service parameters. Use of primitive types leads to reduced serialization, automatic and efficient validation by the .NET Framework.
Prefer the Message-Style Design for Your Web Service
There are two styles of invocation for a Web service – RPC or messaging. The choice radically impacts the way the Web service interface is designed.
The RPC style model is based on objects and methods. We pass parameters and expect an output. This style relies on a synchronous programming model of making a request and waiting for a response. The SOAP-RPC style encoding for Web services maps to the RPC style invocation. If you are designing for RPC style invocation then use the RPC-literal encoding style for greater efficiency. An example of a Web method which is designed for RPC invocation is shown below:
MyMethod1(Employee e)
MyMethod2(int a, string b)
The message-style model is data-centric in nature. The client prepares and sends XML to the Web service without requiring the data to have an object representation. The XML can be any message payload that is appropriately defined by the schema specified for the request. The client can use asynchronous communication and does not immediately expect the response and can continue executing. The message serves as a data contract between the Web service and its clients. The SOAP-Document style encoding is used for designing messaging-style invocations. An example of a Web method which follows this design is shown below:
// Client
string myString = “<mything>thing</mything>”;
MyMethod(myString);
//server
[WebMethod]
void MyMethod(string myString){ . . . }
The message can be encapsulated in a simple string type or in an XmlElement. Some of the advantages of using message-style invocation include:
- it supports asynchronous invocation.
- The SOAP-Document style encoding involves less XML marshalling of data over the wire in comparison to SOAP-RPC encoding.
- The schema serves as a data-contract between the client and the server and can easily be changed without creating multiple versions of the same method. This is because any XML message can be passed as a single parameter as a string.
- Validation of the complete incoming message at the server is possible by using a schema. This helps you avoid costly redundant processing if the inbound message is invalid.
- Because the message-style model requires sending a prepared XML string to the Web service, you can use your own serialization mechanism for improved efficiency rather than depending upon XmlSerializer.
Approaches to Caching
Web service performance can be enhanced greatly by caching data. With ASP.NET Web services, you can use many of the same caching features that are available to ASP.NET Web applications. These include ASP.NET output caching, HTTP response caching and ASP.NET application caching.
In common with any caching solution, the caching design for a Web service must consider issues such as how frequently the cached data needs to be updated, whether or not the data is user specific or application wide, what mechanism to use to indicate that the cache needs updating and so on.
Caching is a great way to improve Web service performance. By reducing the average request time and easing server load, caching also helps scalability.
Caching can be done for frequently used data applicable to all users or can cache SOAP response output.
Validate Input before Processing It
Validating input early avoids unnecessary server-side processing if the input is invalid for example because it does not adhere to the correct schema. Input data can be validated either by using SoapExtensions or by using separate internal helper methods that Web methods call. The advantage using SoapExtension is that it enables us to separate your validation code from the business logic. If there is any schema change in the future the extension can change independently of the Web method.
Avoid Maintaining State between Calls
Avoid maintaining state between multiple Web service calls from the same client. To maintain state across calls you need to use session state. This might be in-process state, state maintained in a separate state service process or in a database. In each case, additional resources and processing is required. To avoid maintaining state on the server, consider passing any required state to and from the client.
Avoid Calling Local Web Services
Web services located on the same machine as a client ASP.NET application share the same thread pool with the ASP.NET application. Hence the client application and the Web service share the same threads and other related resources such as CPU for request processing.
In addition, the maxConnection attribute Machine.config has no affect on the connection limit for making calls to local Web services. Hence local Web services always tend to give preference to the requests coming from the local machine over and above the requests coming from different machines. This degrades the throughput of the Web service for remote clients.

























































