SilverlightSerializer v2 Test Run With Compression

SilverlightSerializer is a fast binary serializer that works in both .NET and Silverlight, allowing you to move your objects between the two instances or store and retrieve them locally in either. It is highly performant and produces small byte arrays which are suitable for further compression.

I've written about Mike Talbot's SilverlightSerializer before.    Mike's page on it is here.     

Silverlight Serializer can serialize and rehydrate just about anything, including complex multi-dimensional arrays of complex objects. By default it can only serialize public fields and properties for classes with a parameterless constructor however you can handle events to construct objects that require parameters for construction and you can write a custom serializer for a particular type.

The serializer can also produce Checksums that can be used to compare different objects to see if they have the same meaning, or to use as keys to see if you have a cached version already available.

Silverlight Serializer can be used to send information to and from a server using WCF or an ASHX, to create undo buffers for your app or to save things to the file system on either Silverlight or .NET.  You can also use it to deep copy your objects.

In some basic performance testing on .NET4 it proved comparable to BinaryFormatter when serializing (slightly slower), produced files about 30% of the size of those created by BinaryFormatter and deserializes 60% faster.

Silverlight Serializer is thread safe.

What I have done here is to create a solution that contains both a Test console app, and the source code for SilverlightSerializer, along with a copy of the QuickLZ compression codec (which is also Silverlight compatible).

The idea was to creat a List<T> of 100 objects (a Person class that has an IList<Address> property), serialize it, compress that, then decompress and deserialize it as a proof of concept. I created test code for both SilverlightSerializer and the .NET Framework BinaryFormatter to compare both speed and size of the compressed byte arrays, as well as comparing the DataContractSerializer.

You can set a Full Framework 4.0 reference to a Silverlight assembly and it will work, but you have to do it using the Browse feature and browse directly to the compiled assembly. As long as the Silverlight assembly only references Mscorlib, System, and System.Core, it will be full-framework compatible. What this means is that you can handle serialization and compression in your Silverlight application, send the byte array over the wire to a WCF Service that uses the full Framework, and it will be able to use the same code to perform serialization / deserialization, and compression / decompression.

Each of my tests serializes a List<Person> containing 100 instances, compresses it, then decompresses and deserializes. Each full operation is timed, and the size of the stored compressed byte array is measured. Here are the results of my test:

SilverightSerializer:      196 ms    2863 bytes
BinaryFormatter:          129 ms   7651 bytes
DataContractSerializer: 932 ms   3800 bytes

The SilverlightSerializer is a bit slower than the BinaryFormatter (mostly during the serialization process), but it produces a byte array only 37 percent as large. This is especially ideal when you consider that the DataContractSerializer, which is the standard means of serialization for WCF, produces a byte array of comparable size, but takes nearly five times as long as the SilverlightSerializer for the entire process.

Here is the test code, and you can download the complete solution at the bottom:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using QuickLZSharp;
using Serialization;

namespace Tester
{
    class Program
    {
         static void Main(string[] args)
        {
           List<Person> people = new List<Person>();

             for (int i = 0; i < 100; i++)
            {
                Person p = new Person();
                p.FirstName = "Joe";
                p.LastName = "Lastname" + i.ToString();
                p.Id = i;
                p.Email = "joe" + i.ToString() + "@bork.com";
                p.Phone = "1234564444";

               List<Address> addresses = new List<Address>();
                 for (int j = 0; j < 2; j++)
                {
                    Address a = new Address();
                    a.AddressType = "Type" + i.ToString();
                    a.City = "MyCity";
                    a.State = "FL";
                    a.Street = "12 North Street";
                    a.Zipcode = "32101";
                     addresses.Add(a);
                }
                p.Addresses = addresses;
                 people.Add(p);
            }

            // Use Silverlight Serializer:
            Stopwatch sw = Stopwatch.StartNew();
            byte[] b= SilverlightSerializer.Serialize(people);
            byte[] b2=  b.Compress();
            byte[] b3 = b2.Decompress();
           List<Person> newPeople =(List<Person>) SilverlightSerializer.Deserialize(b3);
            sw.Stop();
           Console.WriteLine("                  ms:   size:" );
           Console.WriteLine( "SLSerializer:     " +sw.ElapsedMilliseconds + "  " +b2.Length );

             // Use BinaryFormatter:
            Stopwatch sw2 = Stopwatch.StartNew();
            BinaryFormatter bf = new BinaryFormatter();
            MemoryStream ms = new MemoryStream();
            bf.Serialize(ms, people);
            ms.Seek(0, 0);
            byte[] b4 = ms.ToArray();
            byte[] b5 = b4.Compress();
            byte[] b6 = b5.Decompress();
            MemoryStream ms2 = new MemoryStream(b6);
           List<Person> newPeople2 = (List<Person>) bf.Deserialize(ms2);
            sw2.Stop();
           Console.WriteLine( "Binary Formatter: " +sw2.ElapsedMilliseconds + "  "+ b5.Length );

             //Use DataContractSerializer:
            Stopwatch sw3 = Stopwatch.StartNew();
            DataContractSerializer dcs = new DataContractSerializer(typeof(List<Person >));
            MemoryStream ms3 = new MemoryStream();
            dcs.WriteObject(ms3,people);
            byte[] b7 = ms3.ToArray();
            byte[] b8 = b7.Compress();
            byte[] b9 = b8.Decompress();
            MemoryStream ms4 = new MemoryStream(b9);
           List<Person> people2  =(List<Person>)dcs.ReadObject(ms4);
            sw3.Stop();
           Console.WriteLine("DataContract:     " + sw3.ElapsedMilliseconds + "  " + b8.Length);
           Console.ReadLine();
        }
    }
}

You can download the complete Visual Studio 2010 solution here.
NOTE: This code uses Silverlight 5. You can download the required runtime and Tools here.

By Peter Bromberg   Popularity  (5106 Views)