ASP.NET 2.0 Performance Guidelines - Session State

From Guidance Share

Jump to: navigation, search

- J.D. Meier, Srinath Vasireddy, Ashish Babbar, John Allen, and Alex Mackman


Contents

Choose Basic Types to Reduce Serialization Costs

When using StateServer or SQLServer state stores prefer using basic types such as Int, Byte, Decimal, String, DateTime, TimeSpan, Guid, IntPtr, and UintPrt for storing in session state.

If you have to use complex types, you can use the Serializable attribute, or you can implement the ISerializable interface.

Note You should only implement the ISerializable interface as a last resort. New formatters provided by future versions of the .NET Framework and improvements to the framework provided serialization will not be utilized once you take this approach. Prefer the NonSerialized attribute.


Why

You incur serialization overhead when using StateServer or SQLServer state stores. The simpler the object graph, the faster it should serialize. ASP.NET uses an optimized internal serialization method to serialize basic types. Complex types are serialized using a relatively slow BinaryFormatter object. Hence using the basic types for storing in session state improves the performance of the application.

Using ISerializable interface provides you with more precise control and may speed up serialization resulting in better performance of the application using complex types to store state. But In general, you should avoid implementing ISerializable for the following reasons:

  • It requires derived classes to implement ISerializable to participate in serialization.
  • It requires that you override the constructor and GetObjectData.
  • It limits the type from taking advantage of future features and performance improvements.


When

You should follow this guidelines whenever using StateServer or SQLServer state stores for performance sensitive application.


How

When using complex types you can use Serializable attribute or implement the ISerializable interface.

Using Serializable attribute When you use the Serializable attribute, .NET run-time serialization uses reflection to identify the data that should be serialized. All non transient fields are serialized, including public, private, protected, and internal fields. XML serialization uses reflection to generate special classes to perform the serialization.

You can use attributes to prevent specific fields in your class from being serialized. This reduces the size of the output stream and reduces serialization processing overhead. This technique is also useful to prevent security-sensitive data from being serialized.

There are two attributes: NonSerialized and XmlIgnore. The one you should use depends on the serializer that you are using.

The SoapFormatter and BinaryFormatter classes used by .NET remoting recognize the NonSerialized attribute. The XmlSerializer class used by Web services recognizes the XmlIgnore attribute. The following code fragment shows the XmlIgnore attribute


[Serializable]
public class Employee
{
  public string FirstName;
  [XmlIgnore]  
  public string MiddleName;  
  public string LastName;
}

Implementing the ISerializable interface The ISerializable interface gives you explicit control over how your class is serialized. However, you should only implement this interface as a last resort.

The ISerializable interface contains a single method, GetObjectData, which you use to specify precisely which data should be serialized.


public interface ISerializable
{
  public void GetObjectData(SerializationInfo info, StreamingContext context);
}

The following code shows a simple implementation of the GetObjectData method. Data is retrieved from the current object instance and stored in the SerializationInfo object.


public void GetObjectData(SerializationInfo info, StreamingContext context)
{
  info.AddValue("id", ID);
  info.AddValue("firstName", firstName);
  ...
  info.AddValue("zip", zip);
}

When you implement ISerializable, you must also create a new constructor that accepts SerializationInfo and StreamingContext parameters. This constructor is called by the .NET runtime to de-serialize your object. In the constructor, you read data out of the supplied SerializationInfo object and store the data in the current object instance, as shown in this example.


[Serializable]
public class CustomerInterface : ISerializable
{
  protected CustomerInterface(SerializationInfo info, StreamingContext context)
  {
    ID = info.GetInt32("id");
    firstName = info.GetString("firstName");
    ...
    zip = info.GetString("zip");
  }
  ...
}

Serializing Base Class Members When you implement ISerializable, be sure to serialize base class members. If the base class also implements ISerializable, you can call the base class's GetObjectData. If the base class does not implement ISerializable, you need to store each required value.

Versioning Considerations If you add, remove, or rename the member variables of a class that you have previously serialized, existing persisted objects cannot be successfully de-serialized. This is especially true for classes that do not implement ISerializable and just call GetValue. In this case, an exception is generated if the value you request is not present in the serialized stream.

One way to address this issue is to use a SerializationInfoEnumerator to walk through the items in the SerializationInfo object, and then use a switch to set values. With this approach, you only restore those fields that are present in the serialized stream and you can manually initialize any missing fields.


Problem Example

An ASP.NET human resource web application uses SQLServer as state store. It stores Employee information in session state and uses the default BinaryFormatter for serialization. The issue is not all the Employee information is required later in the application processing. So there is an overhead of serializing too much data, impacting the performance of the data.


[Serializable]
public class Employee
{
  public string FirstName;
  public string MiddleName;
  public string LastName;
  public string Address;
  public int EmpNumber;
  public string BloodGroup;
}


Solution Example

An ASP.NET human resource web application uses SQLServer as State store. It stores Employee information in session state and uses the default binary formatter for serialization. Here the NonSerialized attribute is used to reduce the size of the serialized data stream by instructing the run-time serializers to ignore specific fields within the Employee class. This improves the run-time serialization performance contributing to better performance of the application.


[Serializable]
public class Employee
{
  public string FirstName;
  [NonSerialized]
  public string MiddleName;
  public string LastName;
  [NonSerialized]
  public string Address;
  public int EmpNumber;
  [NonSerialized]
  public string BloodGroup;
}


References

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag/html/scalenetchapt06.asp


Disable Session State If You Do Not Use It

If you do not use session state, disable it.


Why

Disabling session state eliminates redundant session processing performed by ASP.NET, thus improving the performance of the application.


When

You should always disable the session state if you are not using it. You might not use session state because you store simple state on the client and then pass it to the server for each request.

If you are using ViewState for storing simple state, be sure that you don't store large data. As performance degrades with increase in view state.


How

You can disable session state for all applications on the server, for specific applications, or for individual pages, as described in the following list:

For All Applications To disable session state for all applications on your server, use the following element in the Machine.config file.

<system.web>
...
  <sessionState mode='Off'/>
...
</system.web>

You can also remove the session state module from <httpModules> to completely remove session processing overhead.

<system.web>
...
  <httpModules>
  ...
  ...
  </httpModules>
...
</system.web>

For Specific Application To disable session state for a specific application, use the following element in the Web.config file of the application.

<system.web>
...
  <sessionState mode='Off'/>
...
</system.web>

For Specific Web Page To disable session state for a specific Web page, use the following page setting.

<%@ Page EnableSessionState="false" . . .%>


Problem Example

An ASP.NET application is composed entirely of static pages. Unfortunately, it enables session state resulting in unnecessary overhead which has a negative impact on application performance.

<system.web>
...
  <sessionState mode='Inproc'/>
...
</system.web>


Solution Example

An ASP.NET application is composed entirely of static pages. The session state for the static web site is disabled by configuring the Web.config file. This setting allows the application to avoid unnecessary processing overhead associated with session state.

<system.web>
...
  <sessionState mode='Off'/>
...
</system.web>


References


Avoid Storing STA COM Objects in Session State

Storing STA COM objects in session state causes thread affinity. Thread affinity severely affects performance and scalability. If you do use STA COM objects in session state, be sure to set the AspCompat attribute of the @ Page directive.

References


Use the ReadOnly Attribute When You Can

For pages that only need read access to session data, consider setting EnableSessionState to ReadOnly.


Why

Page requests that use session state internally use a ReaderWriterLock object to manage session data. This allows multiple reads to occur at the same time when no lock is held. When the writer acquires the lock to update session state, all read requests are blocked. Normally two calls are made to the database for each request. The first call connects to the database, marks the session as locked, and executes the page. The second call writes any changes and unlocks the session. By setting EnableSessionState to ReadOnly, you avoid blocking, and you send fewer calls to the database thus improving the performance.


When

This is a important guideline and should be followed by all pages which only require read-access to session state.


How

If the session state is required across the application and only few pages need read only access, set the EnableSessionState page directive to ReadOnly to provide read-only access to session variables.

<%@ Page EnableSessionState="ReadOnly" . . .%>

If the session state is not required across the application and only few pages use it, disable session state in the configuration file as follows and set the ReadOnly attribute on a page-by-page basis.

<system.web>
...
  <sessionState mode='Off'/>
...
</system.web>


Problem Example

An ASP.NET application has a few pages which access the session state only for reading the data. By default the pages are forced to use writer lock to session variables while accessing them, this blocks other read operations and also has extra processing overhead.


Solution Example

An ASP.NET application has a few pages which access the session state only for reading the data. These pages set EnableSessionState to ReadOnly, thereby avoid blocking, and sending fewer calls to the database.

<%@ Page EnableSessionState="ReadOnly" . . .%>


References

Personal tools