PaypalMe

Friday, 31 August 2012

Garbage Collection

The .NET Framework uses automatic garbage collection to manage memory for all applications. When you use the new operator to create an object, the object’s memory is obtained from the managed heap. When the garbage collector decides that sufficient garbage has accumulated that it is efficient to do so, it performs a collection to free some memory. This process is fully automatic, but there are a number
of factors that you need to be aware of that can make the process more or less efficient.

To understand the principles of garbage collection, you need to understand the life cycle of a managed object
  1. Memory for an object is allocated from the managed heap when you call new. The object’s constructor is called after the memory is allocated.
  2. The object is used for a period of time.
  3. The object dies due to all its references either being explicitly set to null or else going out of scope.
  4. The object’s memory is freed (collected) some time later. After the memory is freed, it is generally available for other objects to use again

Allocation

The managed heap can be thought of as a block of contiguous memory. When you create a new object, the object’s memory is allocated at the next available location on the managed heap. Because the garbage collector does not need to search for space, allocations are extremely fast if there is enough memory available. If there is not enough memory for the new object, the garbage collector attempts to reclaim
space for the new object.

Collection

To reclaim space, the garbage collector collects objects that are no longer reachable. An object is no longer reachable when there are no references to it, all references are set to null, or all references to it are from other objects that can be collected as part of the current collection cycle.

When a collection occurs, the reachable objects are traced and marked as the trace proceeds. The garbage collector reclaims space by moving reachable objects into the contiguous space and reclaiming the memory used by the unreachable objects. Any object that survives the collection is promoted to the next generation.

Generations

The garbage collector uses three generations to group objects by their lifetime and volatility:
  • Generation 0 (Gen 0). This consists of newly created objects. Gen 0 is collected frequently to ensure that short-lived objects are quickly cleaned up. Those objects that survive a Gen 0 collection are promoted to Generation 1.
  • Generation 1 (Gen 1). This is collected less frequently than Gen 0 and contains longer-lived objects that were promoted from Gen 0. 
  • Generation 2 (Gen 2). This contains objects promoted from Gen 1 (which means it contains the longest-lived objects) and is collected even less frequently. The general strategy of the garbage collector is to collect and move longer-lived objects less frequently.

Key GC Methods 

Below table shows the key methods of the System.GC class. You can use this class to control the behavior of the garbage collector.

Garbage Collection  Methods

Server GC vs. Workstation GC

The CLR provides two separate garbage collectors:
Workstation GC (Mscorwks.dll). This is designed for use by desktop applications such as Windows Forms applications.
Server GC (Mscorsvr.dll). This is designed for use by server applications. ASP.NET loads server GC but only if the server has more than one processor. On single processor servers, it loads workstation GC.

Server GC is optimized for throughput, memory consumption, and multiprocessor scalability, while the workstation GC is tuned for desktop applications. When using the server GC, the managed heap is split into several sections, one per CPU on a multiprocessor computer. When a collection is initiated, the collector has one thread per CPU; all threads collect their own sections simultaneously. The workstation version of the execution engine (Mscorwks.dll) is optimized for smaller latency. Workstation GC performs collection in parallel with the CLR threads. Server GC suspends the CLR threads during collection.

You might sometimes need the functionality of the server GC for your custom application when hosting it on a multiprocessor computer. For example, you might need it for a Windows service that uses a .NET remoting host and is deployed on a multiprocessor server. In this scenario, you need to develop a custom host that loads the CLR and the server GC version of the garbage collector.

Identify and Analyze Your Application’s Allocation Profile

Object size, number of objects, and object lifetime are all factors that impact your application’s allocation profile. While allocations are quick, the efficiency of garbage collection depends (among other things) on the generation being collected. Collecting small objects from Gen 0 is the most efficient form of garbage collection because Gen 0 is the smallest and typically fits in the CPU cache. In contrast, frequent collection of
objects from Gen 2 is expensive. To identify when allocations occur, and which generations they occur in, observe your application’s allocation patterns by using an allocation profiler such as the CLR Profiler.
For more information, see “How To: Use CLR Profiler” in the “How To” section of this guide.

Avoid Calling GC.Collect

The default GC.Collect method causes a full collection of all generations. Full collections are expensive because literally every live object in the system must be visited to ensure complete collection. Needless to say, exhaustively visiting all live objects could, and usually does, take a significant amount of time. The garbage collector’s algorithm is tuned so that it does full collections only when it is likely to be worth the expense of doing so. As a result, do not call GC.Collect directly — let the garbage collector determine when it needs to run.
The garbage collector is designed to be self-tuning and it adjusts its operation to meet the needs of your application based on memory pressure. Programmatically forcing collection can hinder tuning and operation of the garbage collector.
If you have a particular niche scenario where you have to call GC.Collect, consider the following:

Call GC.WaitForPendingFinalizers after you call GC.Collect. This ensures that the current thread waits until finalizers for all objects are called.
After the finalizers run, there are more dead objects (those that were just finalized) that need to be collected. One more call to GC.Collect collects the remaining dead objects.

                System.GC.Collect(); // This gets rid of the dead objects
                System.GC.WaitForPendingFinalizers(); // This waits for any finalizers to finish.
                System.GC.Collect(); // This releases the memory associated with the objects that were just                                finalized.

Consider Using Weak References with Cached Data

Consider using weak references when you work with cached data, so that cached objects can be resurrected easily if needed or released by garbage collection when there is memory pressure. You should use weak references mostly for objects that are not small in size because the weak referencing itself involves some overhead. They are suitable for medium to large-sized objects stored in a collection.

Consider a scenario where you maintain a custom caching solution for the employee information in your application. By holding onto your object through a WeakReference wrapper, the objects are collected when memory pressure grows during periods of high stress. If on a subsequent cache lookup, you cannot find the object, re-create it from the information stored in an authoritative persistent source. In this way, you balance the use of cache and persistent medium. The following code demonstrates how to use a weak reference.

                   void SomeMethod()
                  {
                    // Create a collection
                    ArrayList arr = new ArrayList(5);
                   // Create a custom object
                   MyObject mo = new MyObject();
                   // Create a WeakReference object from the custom object
                  WeakReference wk = new WeakReference(mo);
                  // Add the WeakReference object to the collection
                  arr.Add(wk);
                 // Retrieve the weak reference
                 WeakReference weakReference = (WeakReference)arr[0];
                  MyObject mob = null;
                  if( weakReference.IsAlive ){
                  mob = (MyOBject)weakReference.Target;
                }
                if(mob==null){
                 // Resurrect the object as it has been garbage collected
                 }
                 //continue because we have the object
             }

Prevent the Promotion of Short-Lived Objects

Objects that are allocated and collected before leaving Gen 0 are referred as short-lived objects. The following principles help ensure that your short-lived objects are not promoted:

● Do not reference short-lived objects from long-lived objects. A common example where this occurs is when you assign a local object to a class level object reference.
                   class Customer{
                     Order _lastOrder;
                      void insertOrder (int ID, int quantity, double amount, int productID){
                      Order currentOrder = new Order(ID, quantity, amount, productID);
                      currentOrder.Insert();
                       this._lastOrder = currentOrder;
                         }
                      }
Avoid this type of code because it increases the likelihood of the object being promoted beyond Gen 0, which delays the object’s resources from being reclaimed. One possible implementation that avoids this issue follows.
                      class Customer{
                          int _lastOrderID;
                          void ProcessOrder (int ID, int quantity, double amount, int productID){
                           . . .
                          this._lastOrderID = ID;
                           . . .
                            }
                         }

The specific Order class is brought in by ID as needed.

  • Avoid implementing a Finalize method. The garbage collector must promote finalizable objects to older generations to facilitate finalization, which makes them long-lived objects.
  • Avoid having finalizable objects refer to anything. This can cause the referenced object(s) to become long-lived.

Set Unneeded Member Variables to Null Before Making


Long-Running Calls

Before you block on a long-running call, you should explicitly set any unneeded member variables to null before making the call so they can be collected. This is demonstrated in the following code fragment.
     
                        class MyClass{
                         private string str1;
                         private string str2;
                         void DoSomeProcessing(...){
                         str1= GetResult(...);
                         str2= GetOtherResult(...);
                        }
                          void MakeDBCall(...){
                          PrepareForDBCall(str1,str2);
                          str1=null;
                          str2=null;
                          // Make a database (long running) call
                         }
                         }

This advice applies to any objects which are still statically or lexically reachable but are actually not needed:


  • If you no longer need a static variable in your class, or some other class, set it to null.
  • If you can “prune” your state, that is also a good idea. You might be able to eliminate most of a tree before a long-running call, for instance.
  • If there are any objects that could be disposed before the long-running call, set those to null.
Do not set local variables to null (C#) or Nothing (Visual Basic .NET) because the JIT compiler can statically determine that the variable is no longer referenced and there is no need to explicitly set it to null. The following code shows an example using local variables.

                         void func(...)
                         {
                           String str1;
                           str1="abc";
                           // Avoid this
                           str1=null;
                         }

Minimize Hidden Allocations

Memory allocation is extremely quick because it involves only a pointer relocation to create space for the new object. However, the memory has to be garbage collected at some point and that can hurt performance, so be aware of apparently simple lines of code that actually result in many allocations. For example, String.Split uses a delimiter to create an array of strings from a source string. In doing so, String.Split allocates a new string object for each string that it has split out, plus one object for the array. As a result, using String.Split in a heavy duty context (such as a sorting routine) can be expensive.

                  string attendees = "bob,jane,fred,kelly,jim,ann";
                  // In the following single line the code allocates 6 substrings,
                 // outputs the attendees array, and the input separators array
                 string[] names = attendees.Split( new char[] {','});

Also watch out for allocations that occur inside a loop such as string concatenations using the += operator. Finally, hashing methods and comparison methods are particularly bad places to put allocations because they are often called repeatedly in the context of searching and sorting. For more information about how to handle
strings efficiently

Avoid or Minimize Complex Object Graphs

Try to avoid using complex data structures or objects that contain a lot of references to other objects. These can be expensive to allocate and create additional work for the garbage collector. Simpler graphs have superior locality and less code is needed to maintain them. A common mistake is to make the graphs too general.

Avoid Preallocating and Chunking Memory

C++ programmers often allocate a large block of memory (using malloc) and then use chunks at a time, to save multiple calls to malloc. This is not advisable for managed code for several reasons:
  • Allocation of managed memory is a quick operation and the garbage collector has been optimized for extremely fast allocations. The main reason for preallocating memory in unmanaged code is to speed up the allocation process. This is not an issue for managed code.
  • If you preallocate memory, you cause more allocations than needed; this can trigger unnecessary garbage collections.
  • The garbage collector is unable to reclaim the memory that you manually recycle.
  • Preallocated memory ages and costs more to recycle when it is ultimately released.

Finalize and Dispose Explained

The garbage collector offers an additional, optional service called finalization. Use finalization for objects that need to perform cleanup processing during the collection process and just before the object’s memory is reclaimed. Finalization is most often used to release unmanaged resources maintained by an object; any other use should be closely examined. Examples of unmanaged resources include file handles, database connections, and COM object references.

Finalize

Some objects require additional cleanup because they use unmanaged resources, and these need to be released. This is handled by finalization. An object registers for finalization by overriding the Object.Finalize method. In C# and Managed Extensions for C++, implement Finalize by providing a method that looks like a
C++ destructor.

Note: The semantics of the Finalize method and a C++ destructor should not be confused. The syntax is the same but the similarity ends there.

An object’s Finalize method is called before the object’s managed memory is reclaimed. This allows you to release any unmanaged resources that are maintained by the object. If you implement Finalize, you cannot control when this method should be called because this is left to the garbage collector — this is commonly
referred to as nondeterministic finalization. The finalization process requires a minimum of two collection cycles to fully release the object’s memory. During the first collection pass, the object is marked for finalization. Finalization runs on a specialized thread that is independent from the garbage collector. After finalization occurs, the garbage collector can reclaim the object’s memory. Because of the nondeterministic nature of finalization, there is no guarantee regarding the time or order of object collection. Also, memory resources may be consumed for a large amount of time before being garbage collected. In C#, implement Finalize by using destructor syntax.

                      class yourObject {
                      // This is a finalizer implementation
                      ~yourObject() {
                     // Release your unmanaged resources here
                     . . .
                       }
                     }
The preceding syntax causes the compiler to generate the following code.
             
                    class yourObject {
                        protected override void Finalize() {
                                try{
                                         . . .
                                    }
                                finally {
                                       base.Finalize();
                                     }
                       }

In Visual Basic .NET, you need to override Object.Finalize.
                       
                        Protected Overrides Sub Finalize()
                        ' clean up unmanaged resources
                        End Sub

Dispose

Provide the Dispose method (using the Dispose pattern, which is discussed later in this chapter) for types that contain references to external resources that need to be explicitly freed by the calling code. You can avoid finalization by implementing the IDisposable interface and by allowing your class’s consumers to call Dispose. 
The reason you want to avoid finalization is because it is performed asynchronously and unmanaged resources might not be freed in a timely fashion. This is especially important for large and expensive unmanaged resources such as bitmaps or database connections. In these cases, the classic style of explicitly releasing your resources is preferred (using the IDisposable interface and providing a Dispose method). With
this approach, resources are reclaimed as soon as the consumer calls Dispose and the object need not be queued for finalization. Statistically, what you want to see is that almost all of your finalizable objects are being disposed and not finalized. The finalizer should only be your backup.

With this approach, you release unmanaged resources in the IDisposable.Dispose method. This method can be called explicitly by your class’s consumers or implicitly by using the C# using statement.

To prevent the garbage collector from requesting finalization, your Dispose implementation should call GC.SuppressFinalization.

Finalize and Dispose Guidelines

  • Call Close or Dispose on classes that support it.
  • Use the using statement in C# and Try/Finally blocks in Visual Basic .NET to ensure Dispose is called.
  • Do not implement Finalize unless required.
  • Implement Finalize only if you hold unmanaged resources across client calls.
  • Move the Finalization burden to the leaves of object graphs.
  • If you implement Finalize, implement IDisposable.
  • If you implement Finalize and Dispose, use the Dispose pattern.
  • Suppress finalization in your Dispose method.
  • Allow Dispose to be called multiple times.
  • Call Dispose on base classes and on IDisposable members.
  • Keep finalizer code simple to prevent blocking.
  • Provide thread safe cleanup code only if your type is thread safe.

Thursday, 30 August 2012

Class Design Considerations

Class design choices can affect system performance and scalability. However, analyze your tradeoffs, such as functionality, maintainability, and company coding guidelines. Balance these with performance guidelines.

This section summarizes guidelines for designing your managed classes:

  • Do not make classes thread safe by default.
  • Consider using the sealed keyword.
  • Consider the tradeoffs of virtual members.
  • Consider using overloaded methods.
  • Consider overriding the Equals method for value types.
  • Know the cost of accessing a property.
  • Consider private vs. public member variables.
  • Limit the use of volatile fields.

Do Not Make Classes Thread Safe by Default

Consider carefully whether you need to make an individual class thread safe. Thread safety and synchronization is often required at a higher layer in the software architecture and not at an individual class level. When you design a specific class, you often do not know the proper level of atomicity, especially for lower-level classes.
For example, consider a thread safe collection class. The moment the class needs to be atomically updated with something else, such as another class or a count variable, the built-in thread safety is useless. Thread control is needed at a higher level. There are two problems in this situation. Firstly, the overhead from the thread-safety features that the class offers remains even though you do not require those features. Secondly,
the collection class likely had a more complex design in the first place to offer those thread-safety services, which is a price you have to pay whenever you use the class.

In contrast to regular classes, static classes (those with only static methods) should be thread safe by default. Static classes have only global state, and generally offer services to initialize and manage that shared state for a whole process. This requires proper thread safety.

Consider Using the sealed Keyword

You can use the sealed keyword at the class and method level. In Visual Basic .NET, you can use the NotInheritable keyword at the class level or NotOverridable at the method level. If you do not want anybody to extend your base classes, you should mark them with the sealed keyword. Before you use the sealed keyword at the class level, you should carefully evaluate your extensibility requirements. If you derive from a base class that has virtual members and you do not want anybody to extend the functionality of the derived class, you can consider sealing the virtual members in the derived class. Sealing the virtual methods makes them candidates for inlining and other compiler optimizations.

Consider the following example.


        public class MyClass{
         protected virtual void SomeMethod() { ... }
        }

      You can override and seal the method in a derived class.

        public class DerivedClass : MyClass {
        protected override sealed void SomeMethod () { ... }
        }

This code ends the chain of virtual overrides and makes DerivedClass.SomeMethod a candidate for inlining.

Consider the Tradeoffs of Virtual Members

Use virtual members to provide extensibility. If you do not need to extend your class design, avoid virtual members because they are more expensive to call due to a virtual table lookup and they defeat certain run-time performance optimizations. For example, virtual members cannot be inlined by the compiler. Additionally, when you allow subtyping, you actually present a very complex contract to consumers and you
inevitably end up with versioning problems when you attempt to upgrade your class in the future.

Consider Using Overloaded Methods

Consider having overloaded methods for varying parameters instead of having a sensitive method that takes a variable number of parameters. Such a method results in special code paths for each possible combination of parameters.

           //method taking variable number of arguments
           void GetCustomers (params object [] filterCriteria)
           //overloaded methods
           void GetCustomers (int countryId, int regionId)
           void GetCustomers (int countryId, int regionId, int CustomerType)

Note: If there are COM clients accessing .NET components, using overloaded methods will not work as a strategy.

Use methods with different names instead.

Consider Overriding the Equals Method for Value Types You can override the Equals method for value types to improve performance of the Equals method. The Equals method is provided by System.Object. To use the standard implementation of Equals, your value type must be boxed and passed as an instance of the reference type System.ValueType. The Equals method then uses reflection to perform the comparison. However, the overhead associated with the conversions and reflections can easily be greater than the cost of the actual comparison that needs to be performed. As a result, an Equals method that is specific to your value type can do the required comparison significantly more cheaply. The following code fragment shows an overridden Equals method implementation that improves performance by avoiding reflection costs.

public struct Rectangle{
public double Length;
public double Breadth;
public override bool Equals (object ob) {
if(ob is Rectangle)
return Equals((Rectangle)ob);
else
return false;
}
private bool Equals(Rectangle rect) {
return this.Length == rect.Length && this.Breadth==rect.Breadth;
}
}

Know the Cost of Accessing a Property

A property looks like a field, but it is not, and it can have hidden costs. You can expose class-level member variables by using public fields or public properties. The use of properties represents good object-oriented programming practice because it allows you to encapsulate validation and security checks and to ensure that they are executed when the property is accessed, but their field-like appearance can cause them to be misused.

You need to be aware that if you access a property, additional code, such as validation logic, might be executed. This means that accessing a property might be slower than directly accessing a field. However, the additional code is generally there for good reason; for example, to ensure that only valid data is accepted. For simple properties that contain no additional code (other than directly setting or getting a private member variable), there is no performance difference compared to accessing a public field because the compiler can inline the property code. However, things can easily become more complicated; for example, virtual properties cannot be inlined. If your object is designed for remote access, you should use methods with multiple parameters instead of requiring the client to set multiple properties or fields. This reduces round trips.
It is extremely bad form to use properties to hide complex business rules or other costly operations, because there is a strong expectation by callers that properties are inexpensive. Design your classes accordingly.

Consider Private vs. Public Member Variables

In addition to the usual visibility concerns, you should also avoid unnecessary public members to prevent any additional serialization overhead when you use the XmlSerializer class, which serializes all public members by default.

Limit the Use of Volatile Fields

Limit the use of the volatile keyword because volatile fields restrict the way the compiler reads and writes the contents of the field. The compiler generates the code that always reads from the field’s memory location instead of reading from a register that may have loaded the field’s value. This means that accessing volatile fields is slower than nonvolatile ones because the system is forced to use memory addresses rather than registers.

Reduce Boundary Crossings

Aim to reduce the number of method calls that cross remoting boundaries because this introduces marshaling and potentially thread switching overhead. With managed code, there are several boundaries to consider


● Cross application domain. This is the most efficient boundary to cross because it is within the context of a single process. Because the cost of the actual call is so low, the overhead is almost completely determined by the number, type, and size of parameters passed on the method call.

 Cross process. Crossing a process boundary significantly impacts performance. You should do so only when absolutely necessary. For example, you might determine that an Enterprise Services server application is required for security and fault tolerance reasons. Be aware of the relative performance tradeoff.

 Cross machine. Crossing a machine boundary is the most expensive boundary to cross, due to network latency and marshaling overhead. While marshaling overhead impacts all boundary crossings, its impact can be greater when crossing machine boundaries. For example, the introduction of an HTTP proxy might force
you to use SOAP envelopes, which introduces additional overhead. Before introducing a remote server into your design, you need to consider the relative tradeoffs including performance, security, and administration.

 Unmanaged code. You also need to consider calls to unmanaged code, which introduces marshaling and potentially thread switching overhead. The Platform Invoke (P/Invoke) and COM interop layers of the CLR are very efficient, but performance can vary considerably depending on the type and size of data that
needs to be marshaled between the managed and unmanaged code. 

Performance And Scalability Issues

This will give you a high-level overview of the major issues that can impact the performance and scalability of managed code. There are several main issues that impact managed code

Memory misuse. If you create too many objects, fail to properly release resources,
preallocate memory, or explicitly force garbage collection, you can prevent the
CLR from efficiently managing memory. This can lead to increased working set
size and reduced performance.
Resource cleanup. Implementing finalizers when they are not needed, failing to
suppress finalization in the Dispose method, or failing to release unmanaged
resources can lead to unnecessary delays in reclaiming resources and can
potentially create resource leaks.

Improper use of threads. Creating threads on a per-request basis and not sharing
threads using thread pools can cause performance and scalability bottlenecks for
server applications. The .NET Framework provides a self-tuning thread pool that
should be used by server-side applications.

Abusing shared resources. Creating resources per request can lead to resource
pressure, and failing to properly release shared resources can cause delays in
reclaiming them. This quickly leads to scalability issues.

Type conversions. Implicit type conversions and mixing value and reference types
leads to excessive boxing and unboxing operations. This impacts performance.

Misuse of collections. The .NET Framework class library provides an extensive
set of collection types. Each collection type is designed to be used with specific
storage and access requirements. Choosing the wrong type of collection for
specific situations can impact performance.
Inefficient loops. Even the slightest coding inefficiency is magnified when that
code is located inside a loop. Loops that access an object’s properties are a
common culprit of performance bottlenecks, particularly if the object is remote or
the property getter performs significant work.

Wednesday, 29 August 2012

Application Performance & Scalability

Improving Managed Code Performance

Objectives

  • Optimize assembly and class design.
  • Maximize garbage collection (GC) efficiency in your application.
  • Use Finalize and Dispose properly.
  • Minimize boxing overhead.
  • Evaluate the use of reflection and late binding.
  • Optimize your exception handling code.
  • Make efficient use of iterating and looping constructs.
  • Optimize string concatenation.
  • Evaluate and choose the most appropriate collection type.
  • Avoid common threading mistakes.
  • Make asynchronous calls effectively and efficiently.
  • Develop efficient locking and synchronization strategies.
  • Reduce your application’s working set.
  • Apply performance considerations to code access security.

Ms.Net Framework Diagram.


microsoft .net framework architecture



Application Performance Matters

"46 Percentage of people will leave preferred sites if they experience technical or performance problem". in other words "If your website is slow your customers will go."

When a site fails to load quickly, your first thought will not be "Gee, I wonder what the throughput of the web server is?" Instead you think, "Man this is SLOW! I don't have time for this. I'll find it somewhere else."

Now consider what if it is YOUR Web Site and people are leaving because of poor performance.

Performance is an essential quality attribute of software systems. Failure to meet
performance requirements has many negative consequences, such as:
  • Damaged customer relations
  • Negative press coverage
  • Falling stock prices
  • Business failures
  • Lost income
  • Reduced competitiveness
  • Increased hardware costs
  • Additional project resources
  • Project failure

Managing performance throughout the development process can reduce the risk
of performance failure and lead to performance successes.


Prudent project managers, architects, designers, and programmers know that they
should apply software performance engineering (SPE) methods from the outset of
their projects. They define performance requirements, conduct quantitative
performance analyses starting with the architecture and design, and continuing
throughout development. They apply best practices to implement code that meets
performance requirements as well as functionality, security, reliability,
maintainability, and other quality concerns. They conduct performance
measurements and stress tests to confirm that the system meets its performance
requirements before deployment.