// // // Exe // net6.0 // enable // enable // // // // // // // // all // runtime; build; native; contentfiles; analyzers; buildtransitive // // // // /* BenchmarkDotNet=v0.13.2, OS=Windows 10 (10.0.19044.2006/21H2/November2021Update) AMD Ryzen 9 5950X, 1 CPU, 32 logical and 16 physical cores .NET SDK=7.0.100-rc.1.22431.12 [Host] : .NET 6.0.9 (6.0.922.41905), X64 RyuJIT AVX2 Job-TTHSYX : .NET 6.0.9 (6.0.922.41905), X64 RyuJIT AVX2 IterationCount=1 WarmupCount=1 | Method | Categories | Mean | Error | Ratio | Gen0 | Gen1 | Allocated | Alloc Ratio | |--------------------------- |------------- |---------:|------:|------:|-------:|-------:|----------:|------------:| | MessagePackSerialize | byte[] | 11.06 us | NA | 1.00 | 0.9460 | 0.0458 | 16032 B | 1.00 | | ProtobufNetSerialize | byte[] | 40.88 us | NA | 3.70 | 0.9766 | 0.0610 | 17025 B | 1.06 | | SystemTextJsonSerialize | byte[] | 51.69 us | NA | 4.67 | 2.9297 | 0.1221 | 49521 B | 3.09 | | OrleansSerialize | byte[] | 34.15 us | NA | 3.09 | 6.7139 | 0.3662 | 113032 B | 7.05 | | | | | | | | | | | | MessagePackBufferWriter | BufferWriter | 10.86 us | NA | 1.00 | - | - | - | NA | | ProtobufNetBufferWriter | BufferWriter | 53.34 us | NA | 4.91 | - | - | - | NA | | SystemTextJsonBufferWriter | BufferWriter | 56.52 us | NA | 5.20 | 1.8921 | - | 32344 B | NA | | OrleansBufferWriter | BufferWriter | 33.79 us | NA | 3.11 | 5.7373 | - | 96000 B | NA | | OrleansBufferWriter2 | BufferWriter | 54.26 us | NA | 5.00 | 5.7373 | - | 96000 B | NA | */ using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Columns; using BenchmarkDotNet.Configs; using BenchmarkDotNet.Diagnosers; using BenchmarkDotNet.Exporters; using BenchmarkDotNet.Jobs; using BenchmarkDotNet.Running; using MessagePack; using Microsoft.Extensions.DependencyInjection; using Orleans; using Orleans.Serialization; using Orleans.Serialization.Buffers; using Orleans.Serialization.Session; using ProtoBuf; using System.Buffers; using System.Text; using System.Text.Json; var config = ManualConfig.CreateMinimumViable() .AddDiagnoser(MemoryDiagnoser.Default) .AddExporter(DefaultExporters.Plain) .AddJob(Job.Default.WithWarmupCount(1).WithIterationCount(1)); BenchmarkRunner.Run>(config, args); [MessagePackObject] [ProtoContract] [GenerateSerializer] public struct Vector3 { [Key(0)] [ProtoMember(1)] [Id(0)] public float X; [Key(1)] [ProtoMember(2)] [Id(1)] public float Y; [Key(2)] [ProtoMember(3)] [Id(2)] public float Z; } [CategoriesColumn] [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] public class SerializeTest { T value; ArrayBufferWriter writer; SerializerSessionPool pool; Serializer orleansSerializer; MemoryStream stream; Utf8JsonWriter jsonWriter; public SerializeTest() { if (typeof(T) == typeof(Vector3[])) { value = (T)(object)Enumerable.Repeat(new Vector3 { X = 10.3f, Y = 40.5f, Z = 13411.3f }, 1000).ToArray(); } else { throw new NotSupportedException(); } // Orleans var serviceProvider = new ServiceCollection() .AddSerializer(builder => builder.AddAssembly(typeof(SerializeTest<>).Assembly)) .BuildServiceProvider(); pool = serviceProvider.GetRequiredService(); orleansSerializer = serviceProvider.GetRequiredService>(); // create buffers stream = new MemoryStream(); var serialize1 = orleansSerializer.SerializeToArray(value); var serialize2 = MessagePackSerializer.Serialize(value); ProtoBuf.Serializer.Serialize(stream, value); var serialize3 = stream.ToArray(); stream.Position = 0; var serialize4 = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(value)); writer = new ArrayBufferWriter(new[] { serialize1, serialize2, serialize3, serialize4 }.Max(x => x.Length)); jsonWriter = new Utf8JsonWriter(writer); } // return byte[] [Benchmark(Baseline = true), BenchmarkCategory(" byte[]")] public byte[] MessagePackSerialize() { return MessagePackSerializer.Serialize(value); } [Benchmark, BenchmarkCategory(" byte[]")] public byte[] ProtobufNetSerialize() { ProtoBuf.Serializer.Serialize(stream, value); var array = stream.ToArray(); stream.Position = 0; return array; } [Benchmark, BenchmarkCategory(" byte[]")] public byte[] SystemTextJsonSerialize() { JsonSerializer.Serialize(stream, value); var array = stream.ToArray(); stream.Position = 0; return array; } [Benchmark, BenchmarkCategory(" byte[]")] public byte[] OrleansSerialize() { return orleansSerializer.SerializeToArray(value); } // use BufferWriter [Benchmark(Baseline = true), BenchmarkCategory("BufferWriter")] public void MessagePackBufferWriter() { MessagePackSerializer.Serialize(writer, value); writer.Clear(); } [Benchmark, BenchmarkCategory("BufferWriter")] public void ProtobufNetBufferWriter() { ProtoBuf.Serializer.Serialize(writer, value); writer.Clear(); } [Benchmark, BenchmarkCategory("BufferWriter")] public void SystemTextJsonBufferWriter() { JsonSerializer.Serialize(jsonWriter, value); jsonWriter.Flush(); writer.Clear(); jsonWriter.Reset(writer); } [Benchmark, BenchmarkCategory("BufferWriter")] public void OrleansBufferWriter() { using (var session = pool.GetSession()) { var writer = Writer.CreatePooled(session); try { orleansSerializer.Serialize(value, ref writer); writer.Commit(); } finally { writer.Dispose(); } } } [Benchmark, BenchmarkCategory("BufferWriter")] public void OrleansBufferWriter2() { using (var session = pool.GetSession()) { // wrap ArrayBufferWriter var writer2 = writer.CreateWriter(session); try { orleansSerializer.Serialize(value, ref writer2); writer2.Commit(); } finally { writer2.Dispose(); } writer.Clear(); // clear ArrayBufferWriter } } }