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.Runtime.Serialization.Json; using System.Xml; using System.Xml.Serialization; using Newtonsoft.Json; using Newtonsoft.Json.Bson; using ProtoBuf; using SUtils.Serialization.Formatters; [ProtoContract] [Serializable] public class TestClass : IEquatable { [ProtoMember(1)] public string MyProperty1 { get; set; } [ProtoMember(2)] public int MyProperty2 { get; set; } [ProtoMember(3)] public DateTime MyProperty3 { get; set; } [ProtoMember(4)] public bool MyProperty4 { get; set; } [ProtoMember(5)] public KeyValuePair[] MyProperty5 { get; set; } public bool Equals(TestClass other) { return this.MyProperty1 == other.MyProperty1 && this.MyProperty2 == other.MyProperty2 && this.MyProperty3 == other.MyProperty3 && this.MyProperty4 == other.MyProperty4 && this.MyProperty5.SequenceEqual(other.MyProperty5); } public override int GetHashCode() { return this.MyProperty1.GetHashCode() + this.MyProperty2.GetHashCode(); } } public abstract class SerializerBenchmark { public static readonly List TestData; static SerializerBenchmark() { TestData = Enumerable.Range(1, 100000) .Select(i => new TestClass { MyProperty1 = "hoge" + i, MyProperty2 = i, MyProperty3 = new DateTime(1999, 12, 11).AddDays(i), MyProperty4 = i % 2 == 0, MyProperty5 = Enumerable.Range(1, 10) .ToDictionary(x => x.ToString(), _ => i.ToString()).ToArray() }) .ToList(); } public static SerializerBenchmark Create(T serializer, Func> serializeSelector, Func> deserializeSelector, string optional = null) { return new SerializerBenchmark(serializer, serializeSelector, deserializeSelector, optional); } public abstract void Serialize(); public abstract void Deserialize(); } public class SerializerBenchmark : SerializerBenchmark { private T serializer; private string name; Action serialize; Func deserialize; private string FileName { get { return name + ".temp"; } } public SerializerBenchmark(T serializer, Func> serializeSelector, Func> deserializeSelector, string optional = null) { this.serializer = serializer; this.name = serializer.GetType().Name + ((optional == null) ? "" : " " + optional); this.serialize = serializeSelector(serializer); this.deserialize = deserializeSelector(serializer); } private void Bench(string label, Action action) { GC.Collect(); Console.WriteLine(label + " " + name); var sw = Stopwatch.StartNew(); action(); Console.WriteLine(sw.Elapsed); } private void OpenAndExecute(string path, Action action) { using (var fs = File.Open(path, FileMode.OpenOrCreate)) { action(fs); } } public override void Serialize() { Bench("Serialize", () => OpenAndExecute(FileName, fs => serialize(fs, TestData))); Console.WriteLine(new FileInfo(FileName).Length / 1024 / 1024 + "MB"); } public override void Deserialize() { List data = null; Bench("Deserialize", () => OpenAndExecute(FileName, fs => data = (List)deserialize(fs))); Console.Write("Check => "); Console.WriteLine(TestData.SequenceEqual(data) ? "OK" : "NG"); } } static class Program { static void Main(string[] args) { var bench = new List { SerializerBenchmark.Create(new BinaryFormatter(), x => x.Serialize, x => x.Deserialize), SerializerBenchmark.Create(new XmlSerializer(typeof(List)), x => x.Serialize, x => x.Deserialize), SerializerBenchmark.Create(new DataContractSerializer(typeof(List)), x => x.WriteObject, x => x.ReadObject), SerializerBenchmark.Create(new DataContractSerializer(typeof(List)), x => (s, data) => XmlDictionaryWriter.CreateBinaryWriter(s).Using(xw => x.WriteObject(xw, data)), x => s => XmlDictionaryReader.CreateBinaryReader(s, XmlDictionaryReaderQuotas.Max).Using(xr => x.ReadObject(xr)), "Binary"), SerializerBenchmark.Create(new DataContractJsonSerializer(typeof(List)), x => x.WriteObject, x => x.ReadObject), SerializerBenchmark.Create(new DataContractJsonSerializer(typeof(List)), x => (s, data) => XmlDictionaryWriter.CreateBinaryWriter(s).Using(xw => x.WriteObject(xw, data)), x => s => XmlDictionaryReader.CreateBinaryReader(s, XmlDictionaryReaderQuotas.Max).Using(xr => x.ReadObject(xr)), "Binary"), SerializerBenchmark.Create(new NetDataContractSerializer(), x => x.Serialize, x => x.Deserialize), SerializerBenchmark.Create(new NetDataContractSerializer(), x => (s, data) => XmlDictionaryWriter.CreateBinaryWriter(s).Using(xw => x.WriteObject(xw, data)), x => s => XmlDictionaryReader.CreateBinaryReader(s, XmlDictionaryReaderQuotas.Max).Using(xr => x.ReadObject(xr)), "Binary"), SerializerBenchmark.Create(ProtoBuf.Serializer.CreateFormatter>(), x => x.Serialize, x => x.Deserialize, "- Protocol Buffers"), SerializerBenchmark.Create(new MsgPackFormatter(), x => x.Serialize, x => x.Deserialize, "- MessagePack"), SerializerBenchmark.Create(new JsonSerializer(), x => (s, data) => new StreamWriter(s).Using(sw => new JsonTextWriter(sw).Using(tw=> x.Serialize(tw, data))), x => s => new StreamReader(s).Using(sr => new JsonTextReader(sr).Using(tr=> x.Deserialize>(tr))), "- JSON.NET"), SerializerBenchmark.Create(new JsonSerializer(), x => (s, data) => new BsonWriter(s).Using(bw => x.Serialize(bw, data)), x => s => new BsonReader(s){ReadRootValueAsArray = true}.Using(br => x.Deserialize>(br)), "- JSON.NET BSON") }; bench.ForEach(b => b.Serialize()); Console.WriteLine(); bench.ForEach(b => b.Deserialize()); Console.ReadKey(); } // IDisposable extensions static void Using(this T disposable, Action action) where T : IDisposable { using (disposable) action(disposable); } static TR Using(this T disposable, Func func) where T : IDisposable { using (disposable) return func(disposable); } }