| Improve ASP.Net Web Application Performance |
| This article provides common issues, design guidelines, and coding techniques to improve the performance of ASP.NET Web Application and controls. Building high-performance ASP.NET applications is significantly easier if you design with performance in mind. Make sure you develop a performance plan from the outset of your project. |
|
| Please fill up the form below and we will submit a proposal for your project. Alternatively, you can send email to contact@optionm.net with the project requirements. |
|
|
|
|
|
 |
| Performance Modeling |
|
|
| Performance modeling is a structured and repeatable approach to modeling the performance of your software. It begins during the early phases of your application design and continues throughout the application life cycle.
Performance is generally ignored until there is a problem. There are several problems with this reactive approach: |
|
| Performance problems are frequently introduced early in the design. |
| Design issues cannot always be fixed through tuning or more efficient coding. |
| Fixing architectural or design issues later in the cycle is not always possible. At best, it is inefficient, and is usually very expensive. |
|
| When you create performance models, you identify application scenarios and your performance objectives. Your performance objectives are your measurable criteria, such as response time, throughput (how much work in how much time), and resource utilization (CPU, memory, disk I/O, and network I/O). You break down your performance scenarios into steps and assign performance budgets. Your budget defines the resources and constraints across your performance objectives. |
|
| Performance modeling provides several important benefits: |
| Performance becomes part of your design. |
| Modeling helps answer the question "Will your design support your performance objectives?" By building and analyzing models, you can evaluate tradeoffs before you actually build the solution. |
| You know explicitly what design decisions are influenced by performance and the constraints performance puts on future design decisions. Frequently, these decisions are not captured and can lead to maintenance efforts that work against your original goals. |
| You avoid surprises in terms of performance when your application is released into production. |
| You end up with a document of itemized scenarios that help you quickly see what is important. That translates to where to instrument, what to test for, and how to know whether you are on or off track for meeting your performance goals. |
|
| Upfront performance modeling is not a replacement for scenario-based load testing or prototyping to validate your design. In fact, you have to prototype and test to determine what things cost and to see if your plan makes sense. Data from your prototypes can help you evaluate early design decisions before implementing a design that will not allow you to meet your performance goals. |
|
| Why Model Performance? |
| A performance model provides a path to discover what you do not know. The benefits of performance modeling include the following: |
| Performance becomes a feature of your development process and not an afterthought. |
| You evaluate your tradeoffs earlier in the life cycle based on measurements. |
| Test cases show you whether you are trending toward or away from the performance objectives throughout your application life cycle. |
|
| Modeling allows you to evaluate your design before investing time and resources to implement a flawed design. Having the processing steps for your performance scenarios laid out enables you to understand the nature of your application's work. By knowing the nature of this work and the constraints affecting that work, you can make more informed decisions.
Your model can reveal the following about your application: |
| What are the relevant code paths and how do they affect performance? |
| Where do the use of resources or computations affect performance? |
| Which are the most frequently executed code paths? This helps you identify where to spend time tuning. |
| What are the key steps that access resources and lead to contention? |
| Where is your code in relation to resources (local, remote)? |
| What tradeoffs have you made for performance? |
| Which components have relationships to other components or resources? |
| Where are your synchronous and asynchronous calls? |
| What is your I/O-bound work and what is your CPU-bound work? |
|
| And the model can reveal the following about your goals: |
| What is the priority and achievability of different performance goals? |
| Where have your performance goals affected design? |
|
| Risk Management |
| The time, effort, and money you invest up front in performance modeling should be proportional to project risk. For a project with significant risk, where performance is critical, you may spend more time and energy up front developing your model. For a project where performance is less of a concern, your modeling approach might be as simple as white-boarding your performance scenarios. |
|
| Information in the Performance Model |
| The information in the performance model is divided into different areas. Each area focuses on capturing one perspective. Each area has important attributes that help you execute the process. Table 2.1 shows the key information in the performance model. |
|
| Information in the Performance Model |
| Folder |
Description |
| Application Description |
The design of the application in terms of its layers and its target infrastructure. |
| Scenarios |
Critical and significant use cases, sequence diagrams, and user stories relevant to performance. |
| Performance Objectives |
Response time, throughput, resource utilization. |
| Budgets |
Constraints you set on the execution of use cases, such as maximum execution time and resource utilization levels, including CPU, memory, disk I/O, and network I/O. |
| Measurements |
Actual performance metrics from running tests, in terms of resource costs and performance issues. |
| Workload Goals |
Goals for the number of users, concurrent users, data volumes, and information about the desired use of the application. |
| Baseline Hardware |
Description of the hardware on which tests will be run - in terms of network topology, bandwidth, CPU, memory, disk, and so on. |
|
|
| |
| Other elements of information you might need include those shown in Table below |
| Additional Information You Might Need |
| Folder |
Description |
| Quality-of-Service (QoS) Requirements |
QoS requirements, such as security, maintainability, and interoperability, may impact your performance. You should have an agreement across software and infrastructure teams about QoS restrictions and requirements. |
| Workload Requirements |
Total number of users, concurrent users, data volumes, and information about the expected use of the application. |
|
|
| |
| Inputs |
| A number of inputs are required for the performance modeling process. These include initial (maybe even tentative) information about the following: |
| Scenarios and design documentation about critical and significant use cases. |
| Application design and target infrastructure and any constraints imposed by the infrastructure. |
| QoS requirements and infrastructure constraints, including service level agreements (SLAs). |
| Workload requirements derived from marketing data on prospective customers. |
|
| Outputs |
| The output from performance modeling is the following: |
| A performance model document. |
| Test cases with goals. |
|
| Performance Model Document |
| The performance model document may contain the following: |
| Performance objectives. |
| Budgets. |
| Workloads. |
| Itemized scenarios with goals. |
| Test cases with goals. |
|
| An itemized scenario is a scenario that you have broken down into processing steps. For example, an order scenario might include authentication, order input validation, business rules validation, and orders being committed to the database. The itemized scenarios include assigned budgets and performance objectives for each step in the scenario. |
|
| Process |
| The performance modeling process model is summarized in Figure |
 |
|
| Figure : Eight step performance model |
| The performance modeling process involves the following steps: |
1. Identify key scenarios. Identify scenarios where performance is important and scenarios that pose the most risk to your performance objectives.
2. Identify workload. Identify how many users and concurrent users your system needs to support.
3. Identify performance objectives. Define performance objectives for each of your key scenarios. Performance objectives reflect business requirements.
4. Identify budget. Identity your budget or constraints. This includes the maximum execution time in which an operation must be completed and resource utilization constraints, such as CPU, memory, disk I/O, and network I/O.
5. Identify processing steps. Break down your key scenarios into component processing steps.
6. Allocate budget. Spread your budget (determined in Step 4) across your processing steps (determined in Step 5) to meet your performance objectives (defined in Step 3).
7. Evaluate. Evaluate your design against objectives and budget. You may need to modify your design or spread your response time and resource utilization budget differently to meet your performance objectives.
8. Validate. Validate your model and estimates. This is an ongoing activity and includes prototyping, assessing, and measuring. |
|
|
|
| Click here to submit your project requirements to Option Matrix, India. |
| Back to top |
 |
| Development Architecture |
|
|
| ASP.NET requires a host. On Windows ServerT 2003, the default host is the Internet Information Services (IIS) 6.0 worker process (W3wp.exe). When use the ASP.NET Process Model, the host is the ASP.NET worker process (Aspnet_wp.exe).
When a request is received by ASP.NET, the request is handled by the HttpRuntime object. The HttpRuntime is responsible for application creation and initialization, managing the request queue and thread pool, and dispatching the incoming requests to the correct application. After the request is dispatched to the appropriate application, the request is passed through a pipeline. This pipeline is a staged, event-based execution framework consisting of multiple HttpModule objects and a single HttpHandler object.
This architecture is shown in Figure |
|
 |
|
| Figure: ASP.NET runtime infrastructure |
| HttpModule objects participate in the pipeline by handling predefined events that ASP.NET exposes. These events include BeginRequest, AuthenticateRequest, and EndRequest. The request flows through the pipeline of HttpModule objects and is then run by a single HttpHandler. After the event handler is completed, the request then flows back through the pipeline and is sent to the client.
Throughout the entire lifetime of a request, a context is exposed. The HttpContext object encapsulates information about individual requests and their associated responses. |
|
| Performance and Scalability Issues |
| The main issues that can adversely affect the performance and scalability of your ASP.NET application are summarized below. Subsequent sections in this chapter provide strategies and technical information to prevent or resolve each of these issues. |
|
1. Resource affinity. Resource affinity can prevent you from adding more servers, or resource affinity can reduce the benefits of adding more CPUs and memory. Resource affinity occurs when code needs a specific thread, CPU, component instance, or server.
2. Resource affinity. Resource affinity can prevent you from adding more servers, or resource affinity can reduce the benefits of adding more CPUs and memory. Resource affinity occurs when code needs a specific thread, CPU, component instance, or server.
3. Excessive allocations. Applications that allocate memory excessively on a per-request basis consume memory and create additional work for garbage collection. The additional garbage collection work increases CPU utilization. These excessive allocations may be caused by temporary allocations. For example, the excessive allocations may be caused by excessive string concatenation that uses the += operator in a tight loop.
4. Failure to share expensive resources. Failing to call the Dispose or Close method to release expensive resources, such as database connections, may lead to resource shortages. Closing or disposing resources permits the resources to be reused more efficiently.
5. Blocking operations. The single thread that handles an ASP.NET request is blocked from servicing additional user requests while the thread is waiting for a downstream call to return. Calls to long-running stored procedures and remote objects may block a thread for a significant amount of time.
6. Misusing threads. Creating threads for each request incurs thread initialization costs that can be avoided. Also, using single-threaded apartment (STA) COM objects incorrectly may cause multiple requests to queue up. Multiple requests in the queue slow performance and create scalability issues.
7. Making late-bound calls. Late-bound calls require extra instructions at runtime to identify and load the code to be run. Whether the target code is managed or unmanaged, you should avoid these extra instructions.
8. Misusing COM interop. COM interop is generally very efficient, although many factors affect its performance. These factors include the size and type of the parameters that you pass across the managed/unmanaged boundary and crossing apartment boundaries. Crossing apartment boundaries may require expensive thread switches.
9. Large pages. Page size is affected by the number and the types of controls on the page. Page size is also affected by the data and images that you use to render the page. The more data you send over the network, the more bandwidth you consume. When you consume high levels of bandwidth, you are more likely to create a bottleneck.
10. Failure to use data caching appropriately. Failure to cache static data, caching too much data so that the items get flushed out, caching user data instead of application-wide data, and caching infrequently used items may limit your system's performance and scalability.
11. Failure to use output caching appropriately. If you do not use output caching or if you use it incorrectly, you can add avoidable strain to your Web server.
12. Inefficient rendering. Interspersing HTML and server code, performing unnecessary initialization code on page postback, and late-bound data binding may all cause significant rendering overhead. This may decrease the perceived and true page performance.
Applications that allocate memory excessively on a per-request basis consume memory and create additional work for garbage collection. The additional garbage collection work increases CPU utilization. These excessive allocations may be caused by temporary allocations. For example, the excessive allocations may be caused by excessive string concatenation that uses the += operator in a tight loop.
13. Failure to share expensive resources. Failing to call the Dispose or Close method to release expensive resources, such as database connections, may lead to resource shortages. Closing or disposing resources permits the resources to be reused more efficiently.
14. Blocking operations. The single thread that handles an ASP.NET request is blocked from servicing additional user requests while the thread is waiting for a downstream call to return. Calls to long-running stored procedures and remote objects may block a thread for a significant amount of time.
15. Misusing threads. Creating threads for each request incurs thread initialization costs that can be avoided. Also, using single-threaded apartment (STA) COM objects incorrectly may cause multiple requests to queue up. Multiple requests in the queue slow performance and create scalability issues.
16. Making late-bound calls. Late-bound calls require extra instructions at runtime to identify and load the code to be run. Whether the target code is managed or unmanaged, you should avoid these extra instructions.
17. Misusing COM interop. COM interop is generally very efficient, although many factors affect its performance. These factors include the size and type of the parameters that you pass across the managed/unmanaged boundary and crossing apartment boundaries. Crossing apartment boundaries may require expensive thread switches.
18. Large pages. Page size is affected by the number and the types of controls on the page. Page size is also affected by the data and images that you use to render the page. The more data you send over the network, the more bandwidth you consume. When you consume high levels of bandwidth, you are more likely to create a bottleneck.
19. Failure to use data caching appropriately. Failure to cache static data, caching too much data so that the items get flushed out, caching user data instead of application-wide data, and caching infrequently used items may limit your system's performance and scalability.
20. Failure to use output caching appropriately. If you do not use output caching or if you use it incorrectly, you can add avoidable strain to your Web server.
21. Inefficient rendering. Interspersing HTML and server code, performing unnecessary initialization code on page postback, and late-bound data binding may all cause significant rendering overhead. This may decrease the perceived and true page performance. |
|
|
|
| Click here to submit your project requirements to Option Matrix, India. |
| Back to top |
 |
| Development & Design Considerations |
|
|
| Building high-performance ASP.NET applications is significantly easier if you design with performance in mind. Make sure you develop a performance plan from the outset of your project. Never try to add performance as a post-build step. Also, use an iterative development process that incorporates constant measuring between iterations.
By following best practice design guidelines, you significantly increase your chances of creating a high-performance Web application. Consider the following design guidelines: |
1. Consider security and performance.
2. Partition your application logically.
3. Evaluate affinity.
4. Reduce round trips.
5. Avoid blocking on long-running tasks.
6. Use caching.
7. Avoid unnecessary exceptions. |
|
| Consider Security and Performance |
Your choice of authentication scheme can affect the performance and scalability of your application. You need to consider the following issues: |
|
| Identities. Consider the identities you are using and the way that you flow identity through your application. To access downstream resources, you can use the ASP.NET process identity or another specific service identity. Or, you can enable impersonation and flow the identity of the original caller. If you connect to Microsoft SQL ServerT, you can also use SQL authentication. However, SQL authentication requires you to store credentials in the database connection string. Storing credentials in the database connection string is not recommended from a security perspective. When you connect to a shared resource, such as a database, by using a single identity, you benefit from connection pooling. Connection pooling significantly increases scalability. If you flow the identity of the original caller by using impersonation, you cannot benefit from efficient connection pooling, and you have to configure access control for multiple individual user accounts. For these reasons, it is best to use a single trusted identity to connect to downstream databases. |
Managing credentials. Consider the way that you manage credentials. You have to decide if your application stores and verifies credentials in a database, or if you want to use an authentication mechanism provided by the operating system where credentials are stored for you in the Active Directory® directory service.
You should also determine the number of concurrent users that your application can support and determine the number of users that your credential store (database or Active Directory) can handle. You should perform capacity planning for your application to determine if the system can handle the anticipated load. |
| Protecting credentials. Your decision to encrypt and decrypt credentials when they are sent over the network costs additional processing cycles. If you use authentication schemes such as Windows® Forms authentication or SQL authentication, credentials flow in clear text and can be accessed by network eavesdroppers. In these cases, how important is it for you to protect them as they are passed across the network? Decide if you can choose authentication schemes that are provided by the operating system, such as NTLM or the Kerberos protocol, where credentials are not sent over the network to avoid encryption overhead. |
| Cryptography. If your application only needs to ensure that information is not tampered with during transit, you can use keyed hashing. Encryption is not required in this case, and it is relatively expensive compared to hashing. If you need to hide the data that you send over the network, you require encryption and probably keyed hashing to ensure data validity. When both parties can share the keys, using symmetric encryption provides improved performance in comparison to asymmetric encryption. Although larger key sizes provide greater encryption strength, performance is slower relative to smaller key sizes. You must consider this type of performance and balance the larger key sizes against security tradeoffs at design time. |
|
|
|
| Click here to submit your project requirements to Option Matrix, India. |
| Back to top |
 |
| Architecture and Design Solutions |
|
|
| Here is guide provides the following solutions to help you design Microsoft® .NET applications to meet your performance objectives: |
How to balance performance with quality-of-service (QoS) requirements
Do not consider performance in isolation. Balance your performance requirements with other QoS attributes such as security and maintainability. |
How to identify and evaluate performance issues
Use performance modeling early in the design process to help evaluate your design decisions against your objectives before you commit time and resources. Identify your performance objectives, your workload, and your budgets. Budgets are your constraints. These include maximum execution time and resource utilization such as CPU, memory, disk I/O, and network I/O. |
How to choose a deployment topology
When you design your application architecture, you must take into account corporate policies and procedures together with the infrastructure that you plan to deploy your application on. If the target environment is rigid, your application design must reflect the restrictions that exist in that rigid environment. Your application design must also take into account QoS attributes such as security and maintainability. Sometimes you must make design tradeoffs because of protocol restrictions, and network topologies.
Identify the requirements and constraints that exist between application architecture and infrastructure architecture early in the development process. This helps you choose appropriate architectures and helps you resolve conflicts between application and infrastructure architecture early in the process.
Use a layered design that includes presentation, business, and data access logic. A well-layered design generally makes it easier to scale your application and improves maintainability. A well-layered design also creates predictable points in your application where it makes sense (or not) to make remote calls.
To avoid remote calls and additional network latency, stay in the same process where possible and adopt a non-distributed architecture, where layers are located inside your Web application process on the Web server.
If you do need a distributed architecture, consider the implications of remote communication when you design your interfaces. For example, you might need a distributed architecture because security policy prevents you from running business logic on your Web server, or you might need a distributed architecture because you need to share business logic with other applications, Try to reduce round trips and the amount of traffic that you send over the network. |
How to design for required performance and scalability
Use tried and tested design principles. Focus on the critical areas where the correct approach is essential and where mistakes are often made. Use the categories described by the performance frame that is defined in this guide to help organize and prioritize performance issues. Categories include data structures and algorithms, communication, concurrency, resource management, coupling and cohesion, and caching and state management. |
How to pass data across the tiers
Prioritize performance, maintenance, and ease of development when you select an approach. Custom classes allow you to implement efficient serialization. Use structures if you can to avoid implementing your own serialization. You can use XML for interoperability and flexibility. However, XML is verbose and can require considerable parsing effort. Applications that use XML may pass large amounts of data over the network. Use a DataReader object to render data as quickly as possible, but do not pass DataReader objects between layers because they require an open connection. The DataSet option provides great flexibility; you can use it to cache data across requests. DataSet objects are expensive to create and serialize. Typed DataSet objects permit clients to access fields by name and to avoid the collection lookup overhead. |
How to choose between Web services, remoting, and Enterprise Services
Web services are the preferred communication mechanism for crossing application boundaries, including platform, deployment, and trust boundaries. The Microsoft product team recommendations for working with ASP.NET Web services, Enterprise Services, and .NET remoting are summarized in the following list: |
| Build services by using ASP.NET Web services. |
| Enhance your ASP.NET Web services with Web Services Enhancements (WSE) if you need the WSE feature set and if you can accept the support policy. |
| Use object technology, such as Enterprise Services or .NET remoting, within the implementation of a service. |
| Use Enterprise Services inside your service boundaries when the following conditions are true:
You need the Enterprise Services feature set. This feature set includes object pooling, declarative transactions, distributed transactions, role-based security, and queued components.
You are communicating between components on a local server, and you have performance issues with ASP.NET Web services or WSE. |
| Use .NET remoting inside your service boundaries when the following conditions are true:
You need in-process, cross-application domain communication. Remoting has been optimized to pass calls between application domains extremely efficiently.
You need to support custom wire protocols. Understand, however, that this customization will not port cleanly to future Microsoft implementations.
When you work with ASP.NET Web services, Enterprise Services, or .NET remoting, you should consider the following caveats: |
| If you use ASP.NET Web services, avoid using low-level extensibility features such as the HTTP Context object. If you do use the HttpContext object, abstract your access to it. |
| If you use .NET remoting, avoid or abstract using low-level extensibility such as .NET remoting sinks and custom channels. |
| If you use Enterprise Services, avoid passing object references inside Enterprise Services. Also, do not use COM+ APIs. Instead, use types from the System.EnterpriseServices namespace. |
How to design remote interfaces
When you create interfaces that are designed for remote access, consider the level of chatty communication, the intended unit of work, and the need to maintain state on either side of the conversation.
As a general rule, you should avoid property-based interfaces. You should also avoid any chatty interface that requires the client to call multiple methods to perform a single logical unit of work. Provide sufficiently granular methods. To reduce network round trips, pass data through parameters as described by the data transfer object pattern instead of forcing property access. Also try to reduce the amount of data that is sent over the remote method calls to reduce serialization overhead and network latency.
If you have existing objects that expose chatty interfaces, you can use a data facade pattern to provide a coarse-grained wrapper. The wrapper object would have a coarse-grained interface that encapsulates and coordinates the functionality of one or more objects that have not been designed for efficient remote access.
Alternatively, consider the remote transfer object pattern where you wrap and return the data you need. Instead of making a remote call to fetch individual data items, you fetch a data object by value in a single remote call. You then operate locally against the locally cached data. In some scenarios where you may need to ultimately update the data on the server, the wrapper object exposes a single method that you call to send the data back to the server. |
How to choose between service orientation and object orientation
When you are designing distributed applications, services are the preferred approach. While object-orientation provides a pure view of what a system should look like and is good for producing logical models, a pure object-based approach often does not take into account real-world aspects such as physical distribution, trust boundaries, and network communication. A pure object-based approach also does not take into account nonfunctional requirements such as performance and security.
Table 1 summarizes some key differences between object orientation and service orientation. |
|
| Object Orientation vs. Service Orientation |
| Folder |
Description |
| Assumes homogeneous platform and execution environment. |
Assumes heterogeneous platform and execution environment. |
| Share types, not schemas. |
Share schemas, not types. |
| Assumes cheap, transparent communication. |
Assumes variable cost, explicit communication. |
| Objects are linked: Object identity and lifetime are maintained by the infrastructure. |
Services are autonomous: security and failure isolation are a must. |
| Typically requires synchronized deployment of both client and server. |
Allows continuous separate deployment of client and server. |
| Is easy to conceptualize and thus provides a natural path to follow. |
Builds on ideas from component software and distributed objects. Dominant theme is to manage/reduce sharing between services. |
| Provides no explicit guidelines for state management and ownership. |
Owns and maintains state or uses reference state. |
| Assumes a predictable sequence, timeframe, and outcome of invocations. |
Assumes message-oriented, potentially asynchronous and long-running communications. |
| Goal is to transparently use functions and types remotely. |
Goal is to provide inter-service isolation and wire interoperability based on standards. |
|
|
| Common application boundaries include platform, deployment, trust, and evolution. Evolution refers to whether or not you develop and upgrade applications together. When you evaluate architecture and design decisions around your application boundaries, consider the following: |
| Objects and remote procedure calls (RPC) are appropriate within boundaries. |
| Services are appropriate across and within boundaries. |
|
| Development Solutions |
| Improving Managed Code Performance |
How to conduct performance reviews of managed code
Use analysis tools such as FxCop.exe to analyze binary assemblies and to ensure that they conform to the Microsoft .NET Framework design guidelines.
Use the CLR Profiler tool to look inside the managed heap to analyze problems that include excessive garbage collection activity and memory leaks. |
|
| How to design efficient types |
| Should your classes be thread safe? What performance issues are associated with using properties? What are the performance implications of supporting inheritance? |
|
| How to manage memory efficiently |
| Write code to help the garbage collector do its job efficiently. Minimize hidden allocations, and avoid promoting short-lived objects, preallocating memory, chunking memory, and forcing garbage collections. Understand how pinning memory can fragment the managed heap.
Identify and analyze the allocation profile of your application by using CLR Profiler. |
How to use multithreading in .NET applications
Minimize thread creation, and use the self-tuning thread pool for multithreaded work. Avoid creating threads on a per-request basis. Also avoid using Thread.Abort or Thread.Suspend.
Make sure that you appropriately tune the thread pool for ASP.NET applications and for Web services. For more information, see "How to tune the ASP.NET thread pool" later in this document. |
How to use asynchronous calls
Asynchronous calls may benefit client-side applications where you need to maintain user interface responsiveness. Asynchronous calls may also be appropriate on the server, particularly for I/O bound operations. However, you should avoid asynchronous calls that do not add parallelism and that block the calling thread immediately after initiating the asynchronous call. In these situations, there is no benefit to making asynchronous calls. |
How to clean up resources
Release resources as soon as you have finished with them. Use finally blocks or the C# using statement to make sure that resources are released even if an exception occurs. Make sure that you call Dispose (or Close) on any disposable object that implements the IDisposable interface. Use finalizers on classes that hold on to unmanaged resources across client calls. Use the Dispose pattern to help ensure that you implement Dispose functionality and finalizers (if they are required) correctly and efficiently. |
How to avoid unnecessary boxing
Excessive boxing can lead to garbage collection and performance issues. Avoid treating value types as reference types where possible. Consider using arrays or custom collection classes to hold value types. To identify boxing, examine your Microsoft intermediate language (MSIL) code and search for the box and unbox instructions. |
How to handle exceptions
Exceptions can be expensive. You should not use exceptions for regular application logic. However, use structured exception handling to build robust code, and use exceptions instead of error codes where possible. While exceptions do carry a performance penalty, they are more expressive and less error prone than error codes.
Write code that avoids unnecessary exceptions. Use finally blocks to guarantee resources are cleaned up when exceptions occur. For example, close your database connections in a finally block. You do not need a catch block with a finally block. Finally blocks that are not related to exceptions are inexpensive. |
How to work with strings efficiently
Excessive string concatenation results in many unnecessary allocations that create extra work for the garbage collector. Use StringBuilder when you need to create complex string manipulations and when you need to concatenate strings multiple times. If you know the number of appends and concatenate strings in a single statement or operation, prefer the + operator. Use Response.Write in ASP.NET applications to benefit from string buffering when a concatenated string is to be displayed on a Web page. |
How to choose between arrays and collections
Arrays are the fastest of all collection types, so unless you need special functionalities like dynamic extension of the collection, sorting, and searching, you should use arrays. If you need a collection type, choose the most appropriate type based on your functionality requirements to avoid performance penalties. |
| Use ArrayList to store custom object types and particularly when the data changes frequently and you perform frequent insert and delete operations. Avoid using ArrayList for storing strings. |
| Use a StringCollection to store strings. |
| Use a Hashtable to store a large number of records and to store data that may or may not change frequently. Use Hashtable for frequently queried data such as product catalogs where a product ID is the key. |
| Use a HybridDictionary to store frequently queried data when you expect the number of records to be low most of the time with occasional increases in size. |
| Use a ListDictionary to store small amounts of data (fewer than 10 items). |
| Use a NameValueCollection to store strings of key-value pairs in a presorted order. Use this type for data that changes frequently where you need to insert and delete items regularly and where you need to cache items for fast retrieval. |
| Use a Queue when you need to access data sequentially (first in is first out) based on priority. |
| Use a Stack in scenarios where you need to process items in a last-in, first-out manner. |
| Use a SortedList for fast object retrieval using an index or key. However, avoid using a SortedList for large data changes because the cost of inserting the large amount of data is high. For large data changes, use an ArrayList and then sort it by calling the Sort method. |
How to improve serialization performance
Reduce the amount of data that is serialized by using the XmlIgnore or NonSerialized attributes. XmlIgnore applies to XML serialization that is performed by the XmlSerializer. The XmlSerializer is used by Web services. The NonSerialized applies to .NET Framework serialization used in conjunction with the BinaryFormatter and SoapFormatter. The BinaryFormatter produces the most compact data stream, although for interoperability reasons you often need to use XML or SOAP serialization.
You can also implement ISerializable to explicitly control serialization and to determine the exact fields to be serialized from a type. However, using ISerializable to explicitly control serialization is not recommended because it prevents you from using new and enhanced formatters provided by future versions of the .NET Framework.
If versioning is a key consideration for you, consider using a SerializationInfoEnumerator to enumerate through the set of serialized fields before you try to deserialize them.
To improve DataSet serialization, you can use column name aliasing, you can avoid serializing both the original and the updated data values, and you can reduce the number of DataTable instances that you serialize. |
How to improve code access security performance
Code access security ensures that your code and the code that calls your code are authorized to perform specific privileged operations and to access privileged resources like the file system, the registry, the network, databases, and other resources. The permission asserts and permission demands in the code you write and call directly affects the number and the cost of the security stack walks that you need. |
How to reduce working set size
A smaller working set produces better system performance. Fewer larger assemblies rather than many smaller assemblies help reduce working set size. Using the Native Image Generator (Ngen.exe) to precompile code may also help. |
How to develop SMP friendly code
To write managed code that works well with symmetric multiprocessor (SMP) servers, avoid contentious locks and do not create lots of threads. Instead, favor the ASP.NET thread pool and allow it to decide the number of threads to release.
If you run your application on a multiprocessor computer, use the server GC) instead of the workstation GC. The server GC is optimized for throughput, memory consumption, and multiprocessor scalability. ASP.NET automatically loads the server GC. If you do not use ASP.NET, you have to load the server GC programmatically. The next version of the .NET Framework provides a configurable switch. |
How to time managed code in nanoseconds
Use the Microsoft Win32® functions QueryPerformanceCounter and QueryPerformanceFrequency to measure performance.
Note At the time of this writing, the .NET Framework 2.0 (code-named "Whidbey") provides a wrapper to simplify using QueryPerformanceCounter and QueryPerformanceFrequency. |
How to instrument managed code
Instrument your application to measure your processing steps for your key performance scenarios. You may need to measure resource utilization, latency, and throughput. Instrumentation helps you identify where bottlenecks exist in your application. Make your instrumentation configurable; be able to control event types and to switch your instrumentation off completely. Options for instrumentation include the following: |
| Event Tracing for Windows (ETW). Event Tracing for Windows is the recommended approach because it is the least expensive to use in terms of execution time and resource utilization. |
| Trace and Debug classes. The Trace class lets you instrument your release and debug code. You can use the Debug class to output debug information and to check logic for assertions in code. These classes are in the System.Diagnostics namespace. |
| Custom performance counters. You can use custom counters to time key scenarios within your application. |
Windows Management Instrumentation (WMI). WMI is the core instrumentation technology built into the Microsoft Windows® operating system. Logging to a WMI sink is more expensive compared to other sinks.
Enterprise Instrumentation Framework (EIF). EIF provides a framework for instrumentation. It provides a unified API. You can configure the events that you generate, and you can configure the way the events are logged. |
How to decide when to use the Native Image Generator (Ngen.exe)
The Native Image Generator (Ngen.exe) allows you to run the just-in-time (JIT) compiler on your assembly's MSIL to generate native machine code that is cached to disk. Ngen.exe for the .NET Framework version 1.0 and version 1.1 was primarily designed for the common language runtime (CLR), where it has produced significant performance improvements. To identify whether or not Ngen.exe provides any benefit for your particular application, you need to measure performance with and without using Ngen.exe. Before you use Ngen.exe, consider the following: |
| Ngen.exe is most appropriate for any scenario that benefits from better page sharing and working set reduction. For example, it is most appropriate for client scenarios that require fast startup to be responsive, for shared libraries, and for multiple-instance applications. |
| Ngen.exe is not recommended for ASP.NET version 1.0 and 1.1 because the assemblies that Ngen.exe produces cannot be shared between application domains. At the time of this writing, the .NET Framework 2.0 (code-named "Whidbey") includes a version of Ngen.exe that produces images that can be shared between application domains.
If you do decide to use Ngen.exe: |
| Measure your performance with and without Ngen.exe. |
| Make sure that you regenerate your native image when you ship new versions of your assemblies for bug fixes or for updates, or when something your assembly depends on changes. |
|
|
|
|
| Click here to submit your project requirements to Option Matrix, India. |
| Back to top |
 |
| Improving ASP.NET Performance |
|
|
| The solutions in this section show how to improve ASP.NET performance. |
| How to build efficient Web pages |
| Start by trimming your page size and by minimizing the number and the size of graphics, particularly in low network bandwidth scenarios. Partition your pages to benefit from improved caching efficiency. Disable view state for pages that do not need it. For example, you should disable view state for pages that do not post back to the server or for pages that use server controls. Ensure pages are batch-compiled. Enable buffering so that ASP.NET batches work on the server and avoids chatty communication with the client. You should also know the cost of using server controls. |
How to tune the ASP.NET thread pool
If your application queues requests with idle CPU, you should tune the thread pool. |
For applications that serve requests quickly, consider the following settings in the Machine.config file:
Set maxconnection to 12 times the number of CPUs.
Set maxIoThreads and maxWorkerThreads to 100.
Set minFreeThreads to 88 times the number of CPUs.
Set minLocalRequestFreeThreads to 76 times the number of CPUs. |
| For applications that experience burst loads (unusually high loads) between lengthy periods of idle time, consider testing your application by increasing the minWorkerThreads and minIOThreads settings. |
For applications that make long-running calls, consider the following settings in the Machine.config file:
Set maxconnection to 12 times the number of CPUs.
Set maxIoThreads and maxWorkerThreads to 100.
Now test the application without changing the default setting for minFreeThreads. If you see high CPU utilization and context switching, test by reducing maxWorkerThreads or increasing minFreeThreads. |
| For ASP.NET applications that use the ASPCOMPAT flag, you should ensure that the total thread count for the worker process does not exceed the following value: |
 |
Copy Code |
|
| 75 + ((maxWorkerThread + maxIoThreads) * #CPUs * 2) |
|
How to handle long-running calls
Long-running calls from ASP.NET applications block the calling thread. Under load, this may quickly cause thread starvation, where your application uses all available threads and stops responding because there are not enough threads available. It may also quickly cause queuing and rejected requests. An ASP.NET application that calls a long-running Web service is an application that blocks the calling thread. In this common scenario, you can call the Web service asynchronously and then display a busy page or a progress page on the client. By retaining the Web service proxy in server-side state by polling from the browser by using the refresh tag, you can detect when the Web service call completes and then return the data to the client.
If design changes are not an alternative, consider tuning the thread pool as described earlier. |
How to cache data
ASP.NET can cache data by using the Cache API, by using output caching, or by using partial page fragment caching. Regardless of the implementation approach, you need to consider an appropriate caching policy that identifies the data you want to cache, the place you want to cache the data in, and how frequently you want to update the cache.
To use effective fragment caching, separate the static and the dynamic areas of your page, and use user controls.
You must tune the memory limit for optimum cache performance. |
|
| Improving Web Services Performance |
| The solutions in this section show how to improve Web service performance. |
|
| How to improve Web service performance |
| Start by tuning the thread pool. If you have sufficient CPU and if you have queued work, apply the tuning formula specified in Chapter 10. Make sure that you pool Web service connections. Make sure that you send only the data you need to send, and ensure that you design for chunky interfaces. Also consider using asynchronous server-side processing if your Web service performs extensive I/O operations. Consider caching for reference data and for any internal data that your Web service relies upon. |
How to handle large data transfer
To perform large data transfers, start by checking that the maxRequestLength parameter in the <httpRuntime> element of your configuration file is large enough. This parameter limits the maximum SOAP message size for a Web service. Next, check your timeout settings. Set an appropriate timeout on the Web service proxy, and make sure that your ASP.NET timeout is larger than your Web service timeout.
You can handle large data transfer in a number of ways: |
| Use a byte array parameter. Using a byte array parameter is a simple approach, but if a failure occurs midway through the transfer, the failure forces you to start again from the beginning. When you are uploading data, this approach can also make your Web service subject to denial-of-service attacks. |
| Return a URL. Return a URL to a file, and then use HTTP to download the file. |
| Use streaming. If you need to transfer large amounts of data (such as several megabytes) from a Web method, consider streaming to avoid having to buffer large amounts of data in memory at the server and client. You can stream data from a Web service either by implementing IList or by implementing IXmlSerializable. |
How to handle attachments
You have various options when you are handling attachments by using Web services. When you are choosing an option, consider the following: |
| WS-Attachments. Web Services Enhancements (WSE) version 1.0 and 2.0 support Web services attachments (WS-Attachments). WS-Attachments use Direct Internet Message Encapsulation (DIME) as an encoding format. While DIME is a supported part of WSE, Microsoft is not investing in this approach long term. DIME is limited because the attachments are outside the SOAP envelope. |
| Base64 encoding. For today, you should use Base64 encoding in place of WS-Attachments when you have advanced Web services requirements such as security. Base64 encoding creates a larger message payload that may be up to two times the original size. For messages that have large attachments, you can implement a WSE filter to compress the message by using tools like GZIP before you send the message over the network. If you cannot afford the message size that Base64 introduces and if you can rely on the transport for security (for example, Secure Sockets Layer [SSL] or Internet Protocol Security [IPSec]), consider the WS-Attachments implementation in WSE. Securing the message is preferred to securing the transport so that messages can be routed securely. Transport security only addresses point-to-point communication. |
| SOAP Message Transmission Optimization Mechanism (MTOM). MTOM, which is a derivative work of SOAP Messages with Attachments (SwA), is the likely future interop technology. MTOM is being standardized by the World Wide Web Consortium (W3C) and is easier to compose than SwA.
SwA, also known as WS-I Attachments Profile 1.0, is not supported by Microsoft. |
|
| Improving .NET Remoting Performance |
| The solutions in this section show how to improve .NET remoting performance. |
|
| How to improve .NET remoting performance |
| Remoting is for local, in-process, cross-application domain communication or for integration with legacy systems. If you use remoting, reduce round trips by using chunky interfaces. Improve serialization performance by serializing only the data you need. Use the NonSerialized attribute to prevent unnecessary fields from being serialized. |
|
How to serialize DataSet instances efficiently over remoting
Try to improve serialization efficiency in the following ways: |
| Use column name aliasing to reduce the size of column names. |
| Avoid serializing the original and new values for DataSet fields if you do not need to. |
| Serialize only those DataTable instances in the DataSet that you require. DataSet instances serialize as XML. |
|
| Improving Enterprise Services Performance |
| The solutions in this section show how to improve the performance of your Enterprise Services applications and serviced components. |
How to improve Enterprise Services performance
Only use Enterprise Services if you need a service. If you need a service, prefer library applications for in-process performance. Use Enterprise Services transactions if you need distributed transactions, but be aware that manual transactions that use ADO.NET or T-SQL offer superior performance for transactions against a single resource manager. Remember to balance performance with ease of development. Declarative Enterprise Services transactions offer the easiest programming model. Also consider your transaction isolation level.
Use object pooling for objects that take a long time to initialize. Make sure that you release objects back to the pool promptly. A good way to do this is to annotate your method with the AutoComplete attribute. Also, clients should call Dispos | | | | | |