Object Serialization

By default, ScaleOut’s NamedCache API uses .NET’s BinaryFormatter to perform serialization. This differs from Windows Server AppFabric Caching, which uses the NetDataContractSerializer.

ScaleOut’s NamedCache class allows you to use custom serializers, so, if you would like to continue using the NetDataContractSerializer, you can use the SetCustomSerialization method to register the NetDataContractSerializer as your serializer. Registration needs to be done once for each named cache (typically when your client application first starts up). For example:

// Note: your project must reference System.Runtime.Serialization.dll
using System;
using Soss.Client;
using System.Runtime.Serialization;

class Program
{
  static void Main(string[] args)
  {
    NamedCache cache = CacheFactory.GetCache("Sample Cache");
    NetDataContractSerializer ndcs = new NetDataContractSerializer();

    // Register the serialize/deserialize callbacks that
    // the "Sample Cache" namespace should use:
    cache.SetCustomSerialization(ndcs.Serialize, ndcs.Deserialize);

    // Create/Read/Update/Delete objects as you normally would, and the
    // new serialization callbacks will be used:
    cache.Insert("key1", "NDCS-serialized value",
                 cache.DefaultCreatePolicy, true, false);

    // Note that all instances of "Sample Cache" that are returned by
    // CacheFactory will continue using the custom serialization methods.
  }
}
[Tip] Tip

A custom serialization callback is a great place to perform encryption or compression of your objects. The example in the SetCustomSerialization documentation illustrates how you can use perform compression using a customized serializer.

Improving Serialization Performance

While .NET’s "off the shelf" serializers like the NetDataContractSerializer and the BinaryFormatter are flexible and easy to use, your application’s performance can be greatly enhanced by using leaner serializers such as protobuf-net or msgpack-cli.

Serialization is often one of the top performance bottlenecks in distributed applications—we recommend using a custom serializer like protobuf-net or msgpack-cli for non-trivial data types whenever possible, as they can improve serialization performance by an order of magnitude and often reduce memory usage in the ScaleOut hosts.

The following example illustrates how an application could use Marc Gravell’s protobuf-net library for efficient serialization:

// Note: Add the protobuf-net NuGet package to project.
using System;
using System.IO;
using ProtoBuf;
using Soss.Client;

// Type of protobuf-serialized objects to store:
[ProtoContract]
public class Person
{
    [ProtoMember(1)]
    public string FirstName { get; set; }

    [ProtoMember(2)]
    public string LastName { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        NamedCache cache = CacheFactory.GetCache("Protobuf cache of Persons");

        // Register our callbacks that use the protobuf-net serializer:
        cache.SetCustomSerialization(Serialize, Deserialize);

        // Cache operations now use Protocol Buffer serialization:
        Person person = new Person() { FirstName = "George",
                                       LastName  = "Washington" };

        cache.Insert("president1", person,
                     cache.DefaultCreatePolicy, true, false);
    }

    // Serialization callback:
    static void Serialize(Stream stream, Object obj)
    {
        var person = obj as Person;
        if (person == null) throw new ArgumentException("obj not a person");

        ProtoBuf.Serializer.Serialize<Person>(stream, person);
    }

    // Deserialization callback:
    static object Deserialize(Stream stream)
    {
        return ProtoBuf.Serializer.Deserialize<Person>(stream);
    }

}