Skip to content

Instantly share code, notes, and snippets.

@neuecc
Created September 15, 2022 20:06
Show Gist options
  • Save neuecc/c19bdca5434bf60751dfd02a1529e62f to your computer and use it in GitHub Desktop.
Save neuecc/c19bdca5434bf60751dfd02a1529e62f to your computer and use it in GitHub Desktop.
//<Project Sdk="Microsoft.NET.Sdk">
// <PropertyGroup>
// <OutputType>Exe</OutputType>
// <TargetFramework>net6.0</TargetFramework>
// <ImplicitUsings>enable</ImplicitUsings>
// <Nullable>enable</Nullable>
// </PropertyGroup>
// <ItemGroup>
// <PackageReference Include="BenchmarkDotNet" Version="0.13.2" />
// <PackageReference Include="MessagePack" Version="2.4.35" />
// <PackageReference Include="protobuf-net" Version="3.1.17" />
// <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
// <PackageReference Include="Microsoft.Orleans.CodeGenerator" Version="4.0.0-preview2">
// <PrivateAssets>all</PrivateAssets>
// <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
// </PackageReference>
// <PackageReference Include="Microsoft.Orleans.Serialization" Version="4.0.0-preview2" />
// </ItemGroup>
//</Project>
/*
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<SerializeTest<Vector3[]>>(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>
{
T value;
ArrayBufferWriter<byte> writer;
SerializerSessionPool pool;
Serializer<T> 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<SerializerSessionPool>();
orleansSerializer = serviceProvider.GetRequiredService<Serializer<T>>();
// 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<byte>(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<byte>
var writer2 = writer.CreateWriter(session);
try
{
orleansSerializer.Serialize(value, ref writer2);
writer2.Commit();
}
finally
{
writer2.Dispose();
}
writer.Clear(); // clear ArrayBufferWriter<byte>
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment