diff --git a/MessagePack.sln b/MessagePack.sln index b1a53041..874e9b1e 100644 --- a/MessagePack.sln +++ b/MessagePack.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26228.4 +VisualStudioVersion = 15.0.26206.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{86309CF6-0054-4CE3-BFD3-CA0AA7DB17BC}" EndProject @@ -47,6 +47,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MessagePackAnalyzer.Vsix", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XamarinAndroid", "sandbox\XamarinAndroid\XamarinAndroid.csproj", "{307A14EF-C896-4024-BD80-95A55B22C2AB}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PertNetFramework", "sandbox\PertNetFramework\PertNetFramework.csproj", "{014A3DCE-50A6-4774-A4C1-C66EEAB67133}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -207,6 +209,18 @@ Global {307A14EF-C896-4024-BD80-95A55B22C2AB}.Release|x86.ActiveCfg = Release|Any CPU {307A14EF-C896-4024-BD80-95A55B22C2AB}.Release|x86.Build.0 = Release|Any CPU {307A14EF-C896-4024-BD80-95A55B22C2AB}.Release|x86.Deploy.0 = Release|Any CPU + {014A3DCE-50A6-4774-A4C1-C66EEAB67133}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {014A3DCE-50A6-4774-A4C1-C66EEAB67133}.Debug|Any CPU.Build.0 = Debug|Any CPU + {014A3DCE-50A6-4774-A4C1-C66EEAB67133}.Debug|x64.ActiveCfg = Debug|Any CPU + {014A3DCE-50A6-4774-A4C1-C66EEAB67133}.Debug|x64.Build.0 = Debug|Any CPU + {014A3DCE-50A6-4774-A4C1-C66EEAB67133}.Debug|x86.ActiveCfg = Debug|Any CPU + {014A3DCE-50A6-4774-A4C1-C66EEAB67133}.Debug|x86.Build.0 = Debug|Any CPU + {014A3DCE-50A6-4774-A4C1-C66EEAB67133}.Release|Any CPU.ActiveCfg = Release|Any CPU + {014A3DCE-50A6-4774-A4C1-C66EEAB67133}.Release|Any CPU.Build.0 = Release|Any CPU + {014A3DCE-50A6-4774-A4C1-C66EEAB67133}.Release|x64.ActiveCfg = Release|Any CPU + {014A3DCE-50A6-4774-A4C1-C66EEAB67133}.Release|x64.Build.0 = Release|Any CPU + {014A3DCE-50A6-4774-A4C1-C66EEAB67133}.Release|x86.ActiveCfg = Release|Any CPU + {014A3DCE-50A6-4774-A4C1-C66EEAB67133}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -224,5 +238,6 @@ Global {2F9A6E0C-DE95-4460-96B7-EB72BBEAEE9E} = {86309CF6-0054-4CE3-BFD3-CA0AA7DB17BC} {09B87BEB-D9A3-4EEB-B56A-ED53D27DF1A3} = {86309CF6-0054-4CE3-BFD3-CA0AA7DB17BC} {307A14EF-C896-4024-BD80-95A55B22C2AB} = {BF4C4202-5015-4FBD-80E6-D0F36A06F700} + {014A3DCE-50A6-4774-A4C1-C66EEAB67133} = {BF4C4202-5015-4FBD-80E6-D0F36A06F700} EndGlobalSection EndGlobal diff --git a/sandbox/PertNetFramework/App.config b/sandbox/PertNetFramework/App.config new file mode 100644 index 00000000..731f6de6 --- /dev/null +++ b/sandbox/PertNetFramework/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/sandbox/PertNetFramework/PertNetFramework.csproj b/sandbox/PertNetFramework/PertNetFramework.csproj new file mode 100644 index 00000000..36b320c4 --- /dev/null +++ b/sandbox/PertNetFramework/PertNetFramework.csproj @@ -0,0 +1,80 @@ + + + + + Debug + AnyCPU + {014A3DCE-50A6-4774-A4C1-C66EEAB67133} + Exe + PertNetFramework + PertNetFramework + v4.6.1 + 512 + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\packages\MsgPack.Cli.0.9.0-beta2\lib\net46\MsgPack.dll + + + ..\..\packages\Newtonsoft.Json.10.0.1-beta1\lib\net45\Newtonsoft.Json.dll + + + ..\..\packages\protobuf-net.2.1.0\lib\net451\protobuf-net.dll + + + + + ..\..\packages\System.Threading.Tasks.Extensions.4.3.0\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll + + + ..\..\packages\System.ValueTuple.4.3.0\lib\netstandard1.0\System.ValueTuple.dll + + + + + + + + + ..\..\packages\ZeroFormatter.1.6.4\lib\net45\ZeroFormatter.dll + + + ..\..\packages\ZeroFormatter.Interfaces.1.6.4\lib\net45\ZeroFormatter.Interfaces.dll + + + + + + + + + + + + + {7abb33ee-a2f1-492b-8daf-5df89f0f0b79} + MessagePack + + + + \ No newline at end of file diff --git a/sandbox/PertNetFramework/Program.cs b/sandbox/PertNetFramework/Program.cs new file mode 100644 index 00000000..26fd561a --- /dev/null +++ b/sandbox/PertNetFramework/Program.cs @@ -0,0 +1,352 @@ +using MessagePack; +using System.Linq; +using MessagePack.Formatters; +using MessagePack.Resolvers; +using System; +using System.Diagnostics; +using System.IO; +using ZeroFormatter; +using System.Collections.Generic; +using MessagePack.Internal; +using ProtoBuf; +using System.Collections; +using Newtonsoft.Json; +using System.Text; +using System.IO.Compression; + +namespace PerfnetFramework +{ + [ZeroFormattable] + [ProtoBuf.ProtoContract] + [MessagePackObject] + public class Person : IEquatable + { + [Index(0)] + [Key(0)] + [MsgPack.Serialization.MessagePackMember(0)] + [ProtoMember(1)] + public virtual int Age { get; set; } + [Index(1)] + [Key(1)] + [MsgPack.Serialization.MessagePackMember(1)] + [ProtoMember(2)] + public virtual string FirstName { get; set; } + [Index(2)] + [Key(2)] + [MsgPack.Serialization.MessagePackMember(2)] + [ProtoMember(3)] + public virtual string LastName { get; set; } + [Index(3)] + [MsgPack.Serialization.MessagePackMember(3)] + [Key(3)] + [ProtoMember(4)] + public virtual Sex Sex { get; set; } + + public bool Equals(Person other) + { + return Age == other.Age && FirstName == other.FirstName && LastName == other.LastName && Sex == other.Sex; + } + } + + public enum Sex : sbyte + { + Unknown, Male, Female, + } + + class Program + { + static void Main(string[] args) + { + + var bytes = new byte[0]; + MessagePackBinary.WriteString(ref bytes, 0, "あいうえおあいうえおあいうえお"); + + var p = new Person + { + Age = 99999, + FirstName = "Windows", + LastName = "Server", + Sex = Sex.Male, + }; + Person[] l = Enumerable.Range(1, 100).Select(x => new Person { Age = x, FirstName = "Windows", LastName = "Server", Sex = Sex.Female }).ToArray(); + + Benchmark(p); + Console.WriteLine(); + Benchmark(l); + } + + static void Benchmark(T target) + { + const int Iteration = 10000; // 10000 + + var jsonSerializer = new JsonSerializer(); + var msgpack = MsgPack.Serialization.SerializationContext.Default; + msgpack.GetSerializer().PackSingleObject(target); + MessagePack.MessagePackSerializer.Serialize(target); + LZ4MessagePackSerializer.Serialize(target); + ZeroFormatter.ZeroFormatterSerializer.Serialize(target); + ProtoBuf.Serializer.Serialize(new MemoryStream(), target); + jsonSerializer.Serialize(new JsonTextWriter(new StringWriter()), target); + + + Console.WriteLine(typeof(T).Name + " serialization test"); + Console.WriteLine(); + + Console.WriteLine("Serialize::"); + byte[] data = null; + byte[] data0 = null; + byte[] data1 = null; + byte[] data2 = null; + byte[] data3 = null; + byte[] dataJson = null; + byte[] dataGzipJson = null; + using (new Measure("MsgPack-Cli")) + { + for (int i = 0; i < Iteration; i++) + { + data = msgpack.GetSerializer().PackSingleObject(target); + } + } + + using (new Measure("MessagePack-CSharp")) + { + for (int i = 0; i < Iteration; i++) + { + data0 = MessagePack.MessagePackSerializer.Serialize(target); + } + } + + using (new Measure("MessagePack(LZ4)")) + { + for (int i = 0; i < Iteration; i++) + { + data3 = LZ4MessagePackSerializer.Serialize(target); + } + } + + using (new Measure("ZeroFormatter")) + { + for (int i = 0; i < Iteration; i++) + { + data1 = ZeroFormatter.ZeroFormatterSerializer.Serialize(target); + } + } + + using (new Measure("JsonNet")) + { + for (int i = 0; i < Iteration; i++) + { + using (var ms = new MemoryStream()) + using (var sw = new StreamWriter(ms, Encoding.UTF8, 1024, true)) + using (var jw = new JsonTextWriter(sw)) + { + jsonSerializer.Serialize(jw, target); + } + } + } + + using (new Measure("JsonNet+Gzip")) + { + for (int i = 0; i < Iteration; i++) + { + using (var ms = new MemoryStream()) + using (var gzip = new GZipStream(ms, CompressionLevel.Fastest)) + using (var sw = new StreamWriter(gzip, Encoding.UTF8, 1024, true)) + using (var jw = new JsonTextWriter(sw)) + { + jsonSerializer.Serialize(jw, target); + } + } + } + + using (new Measure("protobuf-net")) + { + for (int i = 0; i < Iteration; i++) + { + using (var ms = new MemoryStream()) + { + ProtoBuf.Serializer.Serialize(ms, target); + } + } + } + + using (var ms = new MemoryStream()) + { + ProtoBuf.Serializer.Serialize(ms, target); + data2 = ms.ToArray(); + } + + using (var ms = new MemoryStream()) + { + using (var sw = new StreamWriter(ms, Encoding.UTF8, 1024, true)) + using (var jw = new JsonTextWriter(sw)) + { + jsonSerializer.Serialize(jw, target); + } + dataJson = ms.ToArray(); + } + using (var ms = new MemoryStream()) + { + using (var gzip = new GZipStream(ms, CompressionLevel.Fastest)) + using (var sw = new StreamWriter(gzip, Encoding.UTF8, 1024, true)) + using (var jw = new JsonTextWriter(sw)) + { + jsonSerializer.Serialize(jw, target); + } + dataGzipJson = ms.ToArray(); + } + + + msgpack.GetSerializer().UnpackSingleObject(data); + MessagePack.MessagePackSerializer.Deserialize(data0); + //ZeroFormatterSerializer.Deserialize(data1); + ProtoBuf.Serializer.Deserialize(new MemoryStream(data2)); + LZ4MessagePackSerializer.Deserialize(data3); + jsonSerializer.Deserialize(new JsonTextReader(new StreamReader(new MemoryStream(dataJson)))); + + Console.WriteLine(); + Console.WriteLine("Deserialize::"); + + using (new Measure("MsgPack-Cli")) + { + for (int i = 0; i < Iteration; i++) + { + msgpack.GetSerializer().UnpackSingleObject(data); + } + } + + using (new Measure("MessagePack-CSharp")) + { + for (int i = 0; i < Iteration; i++) + { + MessagePack.MessagePackSerializer.Deserialize(data0); + } + } + + using (new Measure("MessagePack(LZ4)")) + { + for (int i = 0; i < Iteration; i++) + { + LZ4MessagePackSerializer.Deserialize(data3); + } + } + + using (new Measure("ZeroFormatter")) + { + for (int i = 0; i < Iteration; i++) + { + ZeroFormatterSerializer.Deserialize(data1); + } + } + + using (new Measure("JsonNet")) + { + for (int i = 0; i < Iteration; i++) + { + using (var ms = new MemoryStream(dataJson)) + using (var sr = new StreamReader(ms, Encoding.UTF8)) + using (var jr = new JsonTextReader(sr)) + { + jsonSerializer.Deserialize(jr); + } + } + } + + using (new Measure("JsonNet+Gzip")) + { + for (int i = 0; i < Iteration; i++) + { + using (var ms = new MemoryStream(dataGzipJson)) + using (var gzip = new GZipStream(ms, CompressionMode.Decompress)) + using (var sr = new StreamReader(gzip, Encoding.UTF8)) + using (var jr = new JsonTextReader(sr)) + { + jsonSerializer.Deserialize(jr); + } + } + } + + using (new Measure("protobuf-net")) + { + for (int i = 0; i < Iteration; i++) + { + using (var ms = new MemoryStream(data2)) + { + ProtoBuf.Serializer.Deserialize(ms); + } + } + } + + Console.WriteLine(); + Console.WriteLine("FileSize::"); + var label = ""; + label = "MsgPack-Cli"; Console.WriteLine($"{label,20} {data.Length} Byte"); + label = "MessagePack-CSharp"; Console.WriteLine($"{label,20} {data0.Length} Byte"); + label = "MessagePack(LZ4)"; Console.WriteLine($"{label,20} {data3.Length} Byte"); + label = "ZeroFormatter"; Console.WriteLine($"{label,20} {data1.Length} Byte"); + label = "protobuf-net"; Console.WriteLine($"{label,20} {data2.Length} Byte"); + label = "JsonNet"; Console.WriteLine($"{label,20} {dataJson.Length} Byte"); + label = "JsonNet+GZip"; Console.WriteLine($"{label,20} {dataGzipJson.Length} Byte"); + + Console.WriteLine(); + Console.WriteLine(); + } + + + static string ToHumanReadableSize(long size) + { + return ToHumanReadableSize(new Nullable(size)); + } + + static string ToHumanReadableSize(long? size) + { + if (size == null) return "NULL"; + + double bytes = size.Value; + + if (bytes <= 1024) return bytes.ToString("f2") + " B"; + + bytes = bytes / 1024; + if (bytes <= 1024) return bytes.ToString("f2") + " KB"; + + bytes = bytes / 1024; + if (bytes <= 1024) return bytes.ToString("f2") + " MB"; + + bytes = bytes / 1024; + if (bytes <= 1024) return bytes.ToString("f2") + " GB"; + + bytes = bytes / 1024; + if (bytes <= 1024) return bytes.ToString("f2") + " TB"; + + bytes = bytes / 1024; + if (bytes <= 1024) return bytes.ToString("f2") + " PB"; + + bytes = bytes / 1024; + if (bytes <= 1024) return bytes.ToString("f2") + " EB"; + + bytes = bytes / 1024; + return bytes + " ZB"; + } + } + + struct Measure : IDisposable + { + string label; + Stopwatch sw; + + public Measure(string label) + { + this.label = label; + System.GC.Collect(2, GCCollectionMode.Forced, blocking: true); + this.sw = Stopwatch.StartNew(); + } + + public void Dispose() + { + sw.Stop(); + Console.WriteLine($"{ label,20} {sw.Elapsed.TotalMilliseconds} ms"); + + System.GC.Collect(2, GCCollectionMode.Forced, blocking: true); + } + } +} \ No newline at end of file diff --git a/sandbox/PertNetFramework/Properties/AssemblyInfo.cs b/sandbox/PertNetFramework/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..b97a5d25 --- /dev/null +++ b/sandbox/PertNetFramework/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// アセンブリに関する一般情報は以下の属性セットをとおして制御されます。 +// アセンブリに関連付けられている情報を変更するには、 +// これらの属性値を変更してください。 +[assembly: AssemblyTitle("PertNetFramework")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("PertNetFramework")] +[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// ComVisible を false に設定すると、このアセンブリ内の型は COM コンポーネントから +// 参照できなくなります。COM からこのアセンブリ内の型にアクセスする必要がある場合は、 +// その型の ComVisible 属性を true に設定してください。 +[assembly: ComVisible(false)] + +// このプロジェクトが COM に公開される場合、次の GUID が typelib の ID になります +[assembly: Guid("014a3dce-50a6-4774-a4c1-c66eeab67133")] + +// アセンブリのバージョン情報は次の 4 つの値で構成されています: +// +// メジャー バージョン +// マイナー バージョン +// ビルド番号 +// Revision +// +// すべての値を指定するか、次を使用してビルド番号とリビジョン番号を既定に設定できます +// 既定値にすることができます: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/sandbox/PertNetFramework/packages.config b/sandbox/PertNetFramework/packages.config new file mode 100644 index 00000000..57581f21 --- /dev/null +++ b/sandbox/PertNetFramework/packages.config @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/sandbox/Sandbox/Program.cs b/sandbox/Sandbox/Program.cs index 75a21c7e..d64a26ac 100644 --- a/sandbox/Sandbox/Program.cs +++ b/sandbox/Sandbox/Program.cs @@ -113,6 +113,11 @@ namespace Sandbox { static void Main(string[] args) { + + + var bytes = new byte[0]; + MessagePackBinary.WriteString(ref bytes, 0, "あいうえおあいうえおあいうえお"); + var p = new Person { Age = 99999, @@ -125,6 +130,7 @@ namespace Sandbox Benchmark(p); Console.WriteLine(); Benchmark(l); + } static void Benchmark(T target) diff --git a/src/MessagePack/MessagePack.csproj b/src/MessagePack/MessagePack.csproj index fc1c6a01..484a5e12 100644 --- a/src/MessagePack/MessagePack.csproj +++ b/src/MessagePack/MessagePack.csproj @@ -68,4 +68,8 @@ + + + + \ No newline at end of file diff --git a/tests/MessagePack.Tests/FormatterTest.cs b/tests/MessagePack.Tests/FormatterTest.cs index 4d75345e..bfc957b6 100644 --- a/tests/MessagePack.Tests/FormatterTest.cs +++ b/tests/MessagePack.Tests/FormatterTest.cs @@ -192,5 +192,32 @@ namespace MessagePack.Tests var binary = MessagePackSerializer.Serialize(now); MessagePackSerializer.Deserialize(binary).Is(now); } + + [Fact] + public void StringTest_Part2() + { + var a = "あいうえお"; + var b = new String('あ', 20); + var c = new String('あ', 130); + var d = new String('あ', 40000); + + byte[] bytesA = null; + MessagePackBinary.WriteString(ref bytesA, 0, a).Is(Encoding.UTF8.GetByteCount(a) + 1); + + byte[] bytesB = null; + MessagePackBinary.WriteString(ref bytesB, 0, b).Is(Encoding.UTF8.GetByteCount(b) + 2); + + byte[] bytesC = null; + MessagePackBinary.WriteString(ref bytesC, 0, c).Is(Encoding.UTF8.GetByteCount(c) + 3); + + byte[] bytesD = null; + MessagePackBinary.WriteString(ref bytesD, 0, d).Is(Encoding.UTF8.GetByteCount(d) + 5); + + int readSize = 0; + MessagePackBinary.ReadString(bytesA, 0, out readSize).Is(a); + MessagePackBinary.ReadString(bytesB, 0, out readSize).Is(b); + MessagePackBinary.ReadString(bytesC, 0, out readSize).Is(c); + MessagePackBinary.ReadString(bytesD, 0, out readSize).Is(d); + } } } diff --git a/tests/MessagePack.Tests/MessagePackBinaryTest.cs b/tests/MessagePack.Tests/MessagePackBinaryTest.cs index d02039ed..08399a59 100644 --- a/tests/MessagePack.Tests/MessagePackBinaryTest.cs +++ b/tests/MessagePack.Tests/MessagePackBinaryTest.cs @@ -532,8 +532,7 @@ namespace MessagePack.Tests var referencePacked = packer.PackString(target); referencePacked.Position.Is(returnLength); - referencePacked.Position.Is(bytes.Length); - stream.ToArray().SequenceEqual(bytes).IsTrue(); + stream.ToArray().SequenceEqual(bytes.Take(returnLength).ToArray()).IsTrue(); int readSize; MessagePackBinary.ReadString(bytes, 0, out readSize).Is(target);