Last active
April 25, 2017 04:48
-
-
Save Scooletz/851263e9272ae2d95b1e39a8439dddac to your computer and use it in GitHub Desktop.
ProtofbufRaw vs regular protobuf-net
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.IO; | |
using System.Runtime.CompilerServices; | |
using BenchmarkDotNet.Attributes; | |
using BenchmarkDotNet.Running; | |
using ProtoBuf; | |
namespace Locals | |
{ | |
class Program | |
{ | |
static void Main(string[] args) => BenchmarkRunner.Run<ProtoBenchmark>(); | |
} | |
[ProtoContract] | |
public class Event | |
{ | |
[ProtoMember(1)] | |
public Guid G1 = Guid.NewGuid(); | |
[ProtoMember(2)] | |
public Guid G2 = Guid.NewGuid(); | |
[ProtoMember(3)] | |
public int I1 = 1; | |
[ProtoMember(4)] | |
public int I2 = 1; | |
} | |
public class ProtoBenchmark | |
{ | |
public const int N = 256; | |
static readonly byte[] Bytes = new byte[N]; | |
static readonly MemoryStream Stream = new MemoryStream(Bytes, true); | |
static readonly Event Event = new Event(); | |
public ProtoBenchmark() | |
{ | |
Stream.Seek(0, SeekOrigin.Begin); | |
Serializer.Serialize(Stream, Event); | |
} | |
[Benchmark] | |
public unsafe void StackallocRaw() | |
{ | |
byte* bytes = stackalloc byte[N]; | |
var e = Event; | |
var offset = 0; | |
bytes[offset] = 1; // field header | |
WriteGuid(bytes + offset + 1, ref e.G1); | |
offset = 22; | |
bytes[offset] = 2; // field header | |
WriteGuid(bytes + offset + 1, ref e.G2); | |
offset = 43; | |
bytes[offset] = 3; // field header | |
offset += WriteInt(bytes + offset + 1, ref e.I1); | |
bytes[offset] = 4; // field header | |
offset += WriteInt(bytes + offset + 1, ref e.I2); | |
KeepAlive(bytes); | |
} | |
/// <summary> | |
/// Writes Guid in a proto way on 20 bytes. | |
/// </summary> | |
static unsafe void WriteGuid(byte* bytes, ref Guid guid) | |
{ | |
bytes[0] = 2; // subitem group or whatever there is | |
bytes[1] = 1; // field header | |
var longPtr = (long*)Unsafe.AsPointer(ref guid); | |
*(long*)(bytes + 2) = *longPtr; | |
bytes[10] = 2; // field header | |
*(long*)(bytes + 11) = *longPtr; | |
bytes[19] = 2; // subitem group or whatever there is ends | |
} | |
static unsafe int WriteInt(byte* bytes, ref int value) | |
{ | |
var bytesWritten = 0; | |
do | |
{ | |
var byteToWrite = (int)(byte)(value & sbyte.MaxValue | 128); | |
bytes[bytesWritten] = (byte)byteToWrite; | |
++bytesWritten; | |
} | |
while ((value >>= 7) != 0); | |
return bytesWritten; | |
} | |
[Benchmark] | |
public void Proto() | |
{ | |
Stream.Seek(0, SeekOrigin.Begin); | |
Serializer.Serialize(Stream, Event); | |
} | |
[MethodImpl(MethodImplOptions.NoInlining)] | |
public static unsafe void KeepAlive(byte* ptr) { } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment