Skip to content

Instantly share code, notes, and snippets.

@Scooletz
Last active April 25, 2017 04:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Scooletz/851263e9272ae2d95b1e39a8439dddac to your computer and use it in GitHub Desktop.
Save Scooletz/851263e9272ae2d95b1e39a8439dddac to your computer and use it in GitHub Desktop.
ProtofbufRaw vs regular protobuf-net
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