Return to HomePage




Code Review: Enterprise Services 1.1 Performance

Source: http://msdn.microsoft.com/library/en-us/dnpag/html/ScaleNetChapt13.asp
J.D. Meier, Srinath Vasireddy, Ashish Babbar, Rico Mariani, and Alex Mackman


Overview

Code reviews should be a regular part of your development process. Performance and scalability code reviews focus on identifying coding techniques and design choices that could lead to performance and scalability issues. The review goal is to identify potential performance and scalability issues before the code is deployed. The cost and effort of fixing performance and scalability flaws at development time is far less than fixing them later in the product deployment cycle.
Avoid performance code reviews too early in the coding phase because this can restrict your design options. Also, bear in mind that that performance decisions often involve tradeoffs. For example, it is easy to reduce maintainability and flexibility while striving to optimize code.
This chapter begins by highlighting the most significant issues that time and again result in inefficient code and suboptimal performance. The chapter then presents the review questions you need to ask while reviewing managed code. These questions apply regardless of the type of managed application you are building. Subsequent sections focus on questions specific to ASP.NET, interoperability with unmanaged code, Enterprise Services, Web services, .NET remoting, and data access. The chapter concludes by identifying a set of tools that you can use to help perform your code reviews.
How to Use This Chapter
This chapter presents the questions that you need to ask to expose potential performance and scalability issues in your managed code. To get the most out of this chapter, do the following:
* Jump to topics or read from beginning to end. The main headings in this chapter help you locate the topics that interest you. Alternatively, you can read the chapter from beginning to end to gain a thorough appreciation of the areas to focus on while performing performance-related code reviews.
* Read Chapter 3, "Design Guidelines for Application Performance." Read Chapter 3 to help ensure that you do not introduce bottlenecks at design time.
* Know your application architecture. Before you start to review code, make sure you fully understand your application's architecture and design goals. If your application does not adhere to best practices architecture and design principles for performance, it is unlikely to perform or scale satisfactorily, even with detailed code optimization. For more information, see Chapter 3, "Design Guidelines for Application Performance," and Chapter 4, "Architecture and Design Review of a .NET Application for Performance and Scalability."
* Scope your review. Identify the priority areas in your application where the review should focus. For example, if you have an online transaction processing (OLTP) database, data access is typically the key area where the most number of optimizations are probable. Similarly, if your application contains complex business logic, focus initially on the business layer. While you should focus on high impact areas, keep in mind the end-to-end flow at the application level.
* Read "Application Performance" chapters. Read the "Application Performance and Scalability" chapters found in Part III of this guide to discover technical solutions to problems raised during your code review.
* Update your coding standards. During successive code reviews, identify key characteristics that appear repeatedly and add those to your development department's coding standards. Over time, this helps raise developer awareness of the important issues and helps reduce common performance-related coding mistakes and encourage best practices during development.
* Use and evolve the accompanying checklist in the "Checklists" section of this guide. Use the "Checklist: Code Review" checklist to quickly view and evaluate the guidelines presented in this chapter. Extend and evolve the checklists to reflect your specific application.

Enterprise Services
Use the following review questions to analyze the efficiency of your serviced components and the code that calls your serviced components:
* Do you use object pooling?
* Do you manage resources efficiently?
* Do you use Queued Components?
* Do you use Loosely Coupled Events?
* Do you use COM+ transactions?
* Do you use the Synchronization attribute?

Do You Use Object Pooling?
To ensure that you use object pooling most efficiently and effectively, review the following questions:
* Do you use objects with heavy initialization overhead?
Consider enabling object pooling for objects that perform heavy initialization. Otherwise do not use object pooling. For example, object pooling is well suited to an object that opens a legacy database connection in its constructor.
* Do you need to control the number of objects activated?
You can use object pooling to limit the number of objects. For example, you might want to restrict the number of open legacy database connection. Object pooling provides an effective connection pooling mechanism for the legacy database.
* Do you release objects properly back to pool?
If you use JIT activation, calling SetAbort or SetComplete or using the AutoComplete attribute ensures that an object returns to the pool. Client code should always call Dispose on any object that implements IDisposable, including serviced components.
Consider using JIT activation with object pooling if you call only one method on the pooled object.
* Do you use JIT activation when calling multiple functions?
Do not use JIT activation if the client is going to instantiate the class and call multiple methods. It is more appropriate for single call scenarios.

Do You Manage Resources Efficiently?
Review the following questions to ensure you manage resources efficiently within your serviced component code:
* Do you call Dispose on serviced components?
Make sure that client code always calls Dispose on serviced components. This helps to ensure the speedy release of unmanaged resources. Additionally, calling Dispose on pooled objects (which are not using JIT activation) returns them to the pool.
* Do you call ReleaseComObject on objects that involve Runtime Callable Wrappers?
Identify components that are accessed using RCWs and ensure you call Marshal.ReleaseCOMObject appropriately. Do not call Marshall.ReleaseComObject when you reference a regular (nonqueued, nonevent class) managed serviced component in a library application. In this case, you do not reference an RCW. You reference an RCW in the following situations:
* You reference an unmanaged COM+ component written in native code (for example, a Visual Basic 6.0 component) hosted in either a library or server application.
* You reference an unmanaged queued component in a library or server application.
* You reference an unmanaged Loosely Coupled Event (LCE) class in a library or server application.
* You reference an unmanaged COM component (no COM+).

* Do you call SetAbort as soon as possible?
Call SetAbort immediately on failure so that the transaction can be aborted and resources freed quickly. The SetAbort example shown in Table 13.1 performs faster than using AutoComplete. Note that when you have nested serviced component calls, you should call SetAbort in lower level methods and each method should propagate an error value upwards. Database exceptions should be caught in the class making the call to the database. It should also call SetAbort and return an error message and error code.
Table 13.1: Examples of SetAbort and AutoComplete
SetAbort AutoComplete
if( !DoSomeWork() )
{
		  //Something goes wrong.
		  [ContextUtil.SetAbort();]
	
}
else
{
		  //All goes well.
		  [ContextUtil.SetComplete();]
	
}
AutoComplete
public void Debit(int amount) {
		    // Your code
		    // Commits if no error, otherwise aborts
	
}


Do You Use Queued Components?
When using queued components, you should avoid any time and order dependency in the algorithm for the client. The natural programming model provided by queuing rapidly breaks down if you start to force ordering. Queued Components is a "fire and forget" model, and time and order dependencies will unnecessarily cause unexpected behavior and contention issues.
Do You Use Loosely Coupled Events?
The COM+ Loosely Coupled Event (LCE) service provides a distributed publisher - subscriber model. If you use LCE, you should not use it to broadcast messages to large numbers of subscribers. Review the following questions:
* Do you use LCE for a large number of subscribers?
Evaluate whether you have too many subscribers for an event because LCE is not designed for large multicast scenarios. A good alternative is to use broadcast. The sockets layer has broadcast packet support.
For more information about using the sockets layer, see "Using UDP Services" on MSDN at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconusingudpservices.asp.
* Do you block on the executing thread for publishing of events?
Using queued components lets you publish the events asynchronously without blocking your main executing thread. This can be particularly useful in scenarios where you need to publish events from ASP.NET application but do not want to block the worker thread processing the request.
• Do you fire events to one subscriber at a time?
When a publisher fires an event, the method call does not return until all the subscriber components have been activated and contacted. With large numbers of subscribers, this can severely affect performance. You can use the Fire in parallel option to instruct the event system to use multiple threads to deliver events to subscribers, by using the following attribute.

EventClassAttribute(FireInParallel=true)


Do You Use COM+ Transactions?
If you use COM+ transactions provided by Enterprise Services, review the following questions:
* Do you need distributed COM+ transactions?
The declarative programming model supported by Enterprise Services makes it very easy to add transactional support to your programs. When you need to manage transactions that span multiple resource managers, the Microsoft Distributed Transaction Coordinator (DTC) makes it easy to manage your unit of work. For transactions against a single database, consider ADO.NET or manual T - SQL transactions in stored procedures. Regardless of the type (DTC, ADO.NET transactions, or Microsoft SQL Server™ transactions), avoid using transactions where you do not need to. For example, fetching and displaying records (that are not updatable) in a transaction is an unnecessary overhead.
* Have you chosen the correct isolation level?
The default isolation level in COM+ 1.5 is Serializable, although COM+ 1.5 enables you to change this isolation level. COM+ 1.5 comes with Windows 2003 and Windows XP, but not Windows 2000. Use of the Repeatable Read or Serializable isolation levels can result in database requests being queued and response time increasing, but they provide higher data consistency.
Use ReadCommitted as the default unless you have different data consistency requirements. Lower isolation levels might be appropriate for certain read-only cases. When determining an appropriate level, carefully consider your business rules and the transaction's unit of work. You can configure a component’s isolation level using the Transaction attribute as shown in the following code.

Transaction(Isolation=TransactionIsolationLevel.ReadCommitted)


Do You Use the Synchronization Attribute?
If you use the Synchronization attribute, access to an entire object is synchronized; this ensures that only a single thread executes a given object instance at a time. You should consider more granular approaches, such as using locks or Mutex objects to provide more granular locking and to improve concurrency.
More Information
For more information about the issues raised in this section, see Chapter 8, "Improving Enterprise Services Performance."
Summary
Performance and scalability code reviews are similar to regular code reviews or inspections, except that the focus is on the identification of coding flaws that can lead to reduced performance and scalability.
This chapter has shown how to review managed code for top performance and scalability issues. It has also shown you how to identify other more subtle flaws that can lead to performance and scalability issues.
Performance and scalability code reviews are not a panacea. However, they can be very effective and should be a regular milestone in the development life cycle.
Additional Resource
For more information, see the following resources:
* Chapter 4 "Architecture and Design Review of a .NET Application for Performance and Scalability."
* Chapter 6, "Improving ASP.NET Performance."
* Chapter 7, "Improving Interop Performance."
* Chapter 8, "Improving Enterprise Services Performance."
* Chapter 9, "Improving XML Performance."
* Chapter 10, "Improving Web Services Performance."
* Chapter 11, "Improving Remoting Performance."
* Chapter 12, "Improving ADO.NET Performance."
For printable checklists, see the following checklists in the "Checklists” section of this guide:
* "Checklist: ASP.NET Performance."
* "Checklist: Managed Code Performance."
* "Checklist: Enterprise Services Performance."
* "Checklist: Interop Performance."
* "Checklist: Remoting Performance."
* "Checklist: Web Services Performance."
* "Checklist: XML Performance."
For further reading, see the following resource:
* For more information about designing for performance, see "Performance" on MSDN at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vsent7/html/vxconPerformance.asp?frame=true.




Return to HomePage
Microsoft Communities