Click here to Skip to main content
15,886,518 members
Articles / Programming Languages / C#

A Fast/Compact Serialization Framework

Rate me:
Please Sign up or sign in to vote.
4.85/5 (37 votes)
13 Oct 2010GPL35 min read 281.9K   1.2K   175  
A framework for object serializiation/deserialization that is many times faster and yields a compact output.
/*

OpenNxSerialization Framework
Copyright (C) 2006 - 2008 "NeXtreme Innovations"
[The Next Xtreme in ingenuity]

This program is free software, distributed under the terms of
the GNU General Public License Version 2. See the License file
at the top of the source tree.

*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Reflection;

using NeXtreme.OpenNxSerialization;
using NeXtreme.OpenNxSerialization.Surrogates;
using NeXtreme.OpenNxSerialization.IO;
using NeXtreme.OpenNxSerialization.Configuration;
using NeXtreme.OpenNxSerialization.Native;
using NeXtreme.OpenNxSerialization.Native.Formatters;
using NeXtreme.OpenNxSerialization.Dynamic.Surrogates;

using NeXtreme.CommonTypes;
using NeXtreme.CommonTypes.Utility;
using NeXtreme.Benchmark.Properties;

namespace NeXtreme.Benchmark
{
    /// <summary>
    /// The main entry class for the application.
    /// </summary>
    partial class Program
    {
        static readonly int kIterations = Settings.Default.NumIterations;
        static readonly int kRunCount = Settings.Default.RunCount;
        private static bool mTabularStats = true;

        static Profiler nstats = new Profiler(1, 10);
        static Profiler cstats = new Profiler(1, 10);

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        static void Main(string[] args)
        {
            Configure();
            RunBenchmarks();
        }

        private static void RunBenchmarks()
        {
            ArrayList list = new ArrayList();

            list.Add(new Char());
            list.Add(new Int32());
            list.Add(new Int64());
            list.Add(new Double());
            list.Add(new DateTime());
            list.Add("Hello World!");
            list.Add(new Guid());
            list.Add(SampleEnumeration.Three);

            list.Add(new byte[100]);
            list.Add(new Char[100]);
            list.Add(new Int32[100]);
            list.Add(new Int64[100]);
            list.Add(new Double[100]);
            list.Add(new DateTime[100]);
            list.Add(new String[100]);

            // OpenNxBenchmark nullable int array
            int?[] nullablesArray = new Nullable<int>[100];
            for (int i = 0; i < nullablesArray.Length; i += 1)
                nullablesArray[i] = i;
            list.Add(nullablesArray);
            list.Add(new Int64?[100]);
            list.Add(new Double?[100]);

            // OpenNxBenchmark simple int array
            Hashtable hashtable = new Hashtable();
            hashtable[0] = new Guid[32];
            hashtable[1] = hashtable[0]; hashtable[2] = hashtable[1];
            hashtable[3] = new Guid[32];
            hashtable[4] = hashtable[3]; hashtable[5] = hashtable[4];
            list.Add(hashtable);

           // OpenNxBenchmark sample struct containing float members
            list.Add(new DataPoint());
            
            // OpenNxBenchmark simple INxSerializable class
            list.Add(new CustomNxSerializable());

            // OpenNxBenchmark simple INxSerializable class
            CustomNxSerializable[] sampleParentClassArray = new CustomNxSerializable[100];
            for (int i = 0; i < sampleParentClassArray.Length; i++)
                sampleParentClassArray[i] = new CustomNxSerializable();
            list.Add(sampleParentClassArray);

            // OpenNxBenchmark simple SampleINxSerializableClass class
            list.Add(new SampleINxSerializableClass("SampleINxSerializableClass"));

            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine("Running bencmarks with {0} iterations and {1} runs per iteration...", kIterations, kRunCount);
            Console.WriteLine();

            // Run Memory Benchmarks
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("Memory Comparison");
            Console.WriteLine("-----------------------------------------------------------");
            if (mTabularStats)
            {
                Console.Write("{0,10}, ", "Mem .NET");
                Console.Write("{0,10}, ", "Mem Nx");
                Console.Write("{0,11}, ", "%age Comp");
                Console.Write("{0,10}, ", "Times Comp");
                Console.WriteLine("{0}", "Class Name");
            }
            Console.WriteLine();
            Console.ResetColor();
            foreach (object graph in list)
            {
                CompareMemoryRequirements(graph);
            }
            Console.WriteLine();

            // Run Performance Benchmarks
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("Performance Comparison");
            Console.WriteLine("-----------------------------------------------------------");
            if (mTabularStats)
            {
                Console.Write("{0,10}, ", "Time .NET");
                Console.Write("{0,10}, ", "Time Nx");
                Console.Write("{0,11}, ", "%age Fast");
                Console.Write("{0,10}, ", "Times Fast");
                Console.WriteLine("{0}", "Class Name");
            }
            Console.WriteLine();
            Console.ResetColor();
            foreach (object graph in list)
            {
                ComparePerformance(graph);
            }
            Console.WriteLine();
        }

        /// <summary>
        /// Perform time and space comparisons.
        /// </summary>
        /// <param name="graph"></param>
        static public void ComparePerformance(object graph)
        {
            if (!mTabularStats)
            {
                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.WriteLine("-------------------------------------");
                Console.WriteLine();
                Console.WriteLine("Benchmarking type -- {0}", graph.GetType().FullName);
                Console.WriteLine();
                Console.ResetColor();
            }

            nstats.Measure(kIterations, kRunCount,
                delegate
                {
                    byte[] arr = NativeSerializationHelper.ToByteBuffer(graph);
                    NativeSerializationHelper.FromByteBuffer(arr);
                }
            );
            cstats.Measure(kIterations, kRunCount,
               delegate
               {
                   NxBinaryFormatter formatter = new NxBinaryFormatter();
                   byte[] arr = formatter.ToByteArray(graph);
                   formatter = new NxBinaryFormatter();
                   formatter.FromByteArray(arr);
               }
            );

            if (!mTabularStats)
            {
                Console.ForegroundColor = ConsoleColor.Cyan;
                Console.WriteLine("Time Native serialization = {0,6}", nstats.Total);
                Console.WriteLine("Time NxSerialization      = {0,6}", cstats.Total);
                Console.WriteLine("Performance = {0:F2}% less time, {1:F1} times faster.",
                    100 - (float)cstats.Total / (float)nstats.Total * 100,
                    (float)nstats.Total / (float)cstats.Total);
                Console.ResetColor();
                Console.ForegroundColor = ConsoleColor.White;
                Console.WriteLine();
                Console.WriteLine("Native serialization statistics...");
                Profiler.PrintExtended(nstats);
                Console.WriteLine("NxSerialization statistics...");
                Profiler.PrintExtended(cstats);
                Console.WriteLine();
            }
            else
            {
                Console.Write("{0,10}, ", nstats.Total);
                Console.Write("{0,10}, ", cstats.Total);
                Console.Write("{0,10:F2}%, ", 100 - (float)cstats.Total / (float)nstats.Total * 100);
                Console.Write("{0,10:F2}, ", (float)nstats.Total / (float)cstats.Total);
                Console.ForegroundColor = ConsoleColor.Green;
                Console.WriteLine("{0}", graph.GetType().FullName);
            }
            Console.ResetColor();
        }

        /// <summary>
        /// Compares the sizes of resulting streams.
        /// </summary>
        /// <param name="graph"></param>
        static public void CompareMemoryRequirements(object graph)
        {
            NxBinaryFormatter formatter = new NxBinaryFormatter();
            byte[] arr = NativeSerializationHelper.ToByteBuffer(graph);
            byte[] arr2 = formatter.ToByteArray(graph);

            if (!mTabularStats)
            {
                Console.ForegroundColor = ConsoleColor.Green;
                Console.WriteLine("Stream size Native serialization = {0,6}", arr.Length);
                Console.WriteLine("Stream size NxSerialization      = {0,6}", arr2.Length);
                Console.WriteLine("Compression = {0:F2}% less space, {1:F1} times compact.",
                    100 - (float)arr2.Length / (float)arr.Length * 100,
                    (float)arr.Length / (float)arr2.Length);
                Console.ResetColor();
            }
            else
            {
                Console.Write("{0,10}, ", arr.Length);
                Console.Write("{0,10}, ", arr2.Length);
                Console.Write("{0,10:F2}%, ", 100 - (float)arr2.Length / (float)arr.Length * 100);
                Console.Write("{0,10:F2}, ", (float)arr.Length / (float)arr2.Length);
                Console.ForegroundColor = ConsoleColor.Green;
                Console.WriteLine("{0}", graph.GetType().FullName);
            }
            Console.ResetColor();
        }

        /// <summary>
        /// Performs a deep cloning operation by serializing and then deserializing the object.
        /// </summary>
        /// <param name="graph"></param>
        /// <returns></returns>
        static public object DeepClone(object graph)
        {
            NxBinaryFormatter formatter = new NxBinaryFormatter();
            byte[] arr = formatter.ToByteArray(graph);
            formatter = new NxBinaryFormatter();
            return formatter.FromByteArray(arr);
        }
    }


    internal class NativeSerializationHelper
    {
        static BinaryFormatter formatter = new BinaryFormatter();

        /// <summary>
        /// serialize an objevt into a stream.
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="objectToSend"></param>
        public static void Serialize(Stream stream, object objectToSend)
        {
            formatter.Serialize(stream, objectToSend);
        }

        /// <summary>
        /// deserialize an object from the stream.
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static object Deserialize(Stream stream)
        {
            return formatter.Deserialize(stream);
        }

        /// <summary>
        /// Creates an object from a byte buffer
        /// </summary>
        /// <param name="buffer"></param>
        /// <returns></returns>
        public static object FromByteBuffer(byte[] buffer)
        {
            if (buffer == null) return null;
            using (MemoryStream ms = new MemoryStream(buffer))
            {
                return Deserialize(ms);
            }
        }

        /// <summary>
        /// Serializes an object into a byte buffer.
        /// The object has to implement interface Serializable or Externalizable
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static byte[] ToByteBuffer(object obj)
        {
            if (obj == null) return null;
            using (MemoryStream ms = new MemoryStream())
            {
                Serialize(ms, obj);
                return ms.ToArray();
            }
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
Architect
Pakistan Pakistan
Let a = b ....... (1)
a - b = a - b
a^2 - ab = a^2 - ab
a^2 - ab = a^2 - b^2 (from 1)
a (a - b) = (a + b) (a - b)
a = (a + b) ...... (2)

if a = 1
1 = (1 + 1) (from 1 & 2)
1 = 2 !!

Comments and Discussions