Programming Microsoft ASP.NET 4 - Dino Esposito [359]
Persist Session Data to Remote Servers
The session state loss problem that I mentioned earlier for InProc mode can be neatly solved by employing either of the two predefined out-of-process state providers: StateServer or SQLServer. In this case, though, the session state is held outside the ASP.NET worker process and an extra layer of code is needed to serialize and deserialize it to and from the actual storage medium. This operation takes place whenever a request is processed.
The need to copy session data from an external repository into the local session dictionary might tax the state management process to the point of causing a 15 percent to 25 percent decrease in performance. Note, though, that this is only a rough estimate, and it’s closer to the minimum impact rather than to the maximum impact. The estimate, in fact, does not fully consider the complexity of the types actually saved into the session state.
Note
When you get to choose an out-of-process state provider (for example, StateServer and SQLServer), be aware that you need to set up the runtime environment before putting the application in production. This means either starting a Windows service for StateServer or configuring a database for SQLServer. No preliminary work is needed if you stay with the default, in-process option.
State Serialization and Deserialization
When you use the InProc mode, objects are stored in the session state as live instances of classes. No real serialization and deserialization ever takes place, meaning that you can actually store in Session whatever objects (including COM objects) you have created and access them with no significant overhead. The situation is less favorable if you opt for an out-of-process state provider.
In an out-of-process architecture, session values are copied from the native storage medium into the memory of the AppDomain that processes the request. A serialization/deserialization layer is needed to accomplish the task and represents one of the major costs for out-of-process state providers. How does this affect your code? First, you should make sure that only serializable objects are ever stored in the session dictionary; otherwise, as you can easily imagine, the session state can’t be saved and you’ll sustain an exception, moreover.
To perform the serialization and deserialization of types, ASP.NET uses two methods, each providing different results in terms of performance. For basic types, ASP.NET resorts to an optimized internal serializer; for other types, including objects and user-defined classes, ASP.NET makes use of the .NET binary formatter, which is slower. Basic types are string, DateTime, Guid, IntPtr, TimeSpan, Boolean, byte, char, and all numeric types.
The optimized serializer—an internal class named AltSerialization—employs an instance of the BinaryWriter object to write out one byte to denote the type and then the value. While reading, the AltSerialization class first extracts one byte, detects the type of the data to read, and then resorts to a type-specific method of the BinaryReader class to take data. The type is associated with an index according to an internal table, as shown in Figure 17-3.
Figure 17-3. The serialization schema for basic types that the internal AltSerialization class uses.
Note
While Booleans and numeric types have a well-known size, the length of a string can vary quite a bit. How can the reader determine the correct size of a string? The BinaryReader.ReadString method exploits the fact that on the underlying stream the string is always prefixed with the length, encoded as an integer seven bits at a time. Values of the DateTime type, on the other hand, are saved by writing only the total number of ticks that form the date and are read as an Int64 type.
As mentioned, more complex objects are serialized using the relatively slower BinaryFormatter class as long as the involved types are marked as serializable. Both simple and complex