Skip to content

Instantly share code, notes, and snippets.

@scionwest
Last active May 9, 2017 22:29
Show Gist options
  • Save scionwest/d82f04545f7161642a83037e5c258007 to your computer and use it in GitHub Desktop.
Save scionwest/d82f04545f7161642a83037e5c258007 to your computer and use it in GitHub Desktop.
Method Mean Error StdDev
SerializeProto 849.57 us 12.4482 us 10.3949 us
DeserializeProto 37.37 us 0.4032 us 0.3574 us
SerializeJson 894.04 us 17.0883 us 13.3414 us
DeserializeJson 48.73 us 0.8571 us 0.8017 us
SerializeBinary 1,473.37 us 49.7022 us 140.1859 us
DeserializeBinary 100.19 us 1.9587 us 3.3786 us
using BenchmarkDotNet.Attributes;
using BenchmarkModels;
using Google.Protobuf;
using Newtonsoft.Json;
using System.IO;
namespace AComms.Client
{
public class SerializationBenchmarks
{
private const string _Name = "Jane Doe";
private const string _ProtoFilename = "proto.dat";
[Setup]
public void SetupProtoDeserialization()
{
var request = this.CreateProtoModel();
using (var output = File.Create("ProtoDeserialize.dat"))
{
request.WriteTo(output);
}
File.WriteAllText("JsonDeserialize.json", JsonConvert.SerializeObject(this.CreateClrModel()));
if (File.Exists("binaryData.dat"))
{
File.Delete("binaryData.dat");
}
if (File.Exists("binarydeserialize.dat"))
{
File.Delete("binarydeserialize.dat");
}
var model = this.CreateClrModel();
using (var writer = new BinaryWriter(new FileStream("binarydeserialize.dat", FileMode.CreateNew)))
{
writer.Write(model.Money);
writer.Write(model.Name);
writer.Write(model.PageSize);
writer.Write(model.Query);
writer.Write(model.ResultsPerPage);
writer.Flush();
}
}
[Benchmark]
public void SerializeProtobuf()
{
using (var output = File.Create(_ProtoFilename))
{
var request = this.CreateProtoModel();
request.WriteTo(output);
}
}
[Benchmark]
public void DeserializeProtobuf()
{
using (var input = File.OpenRead("ProtoDeserialize.dat"))
{
HelloRequest request = HelloRequest.Parser.ParseFrom(input);
}
}
[Benchmark]
public void SerializeJson()
{
var json = JsonConvert.SerializeObject(this.CreateClrModel());
File.WriteAllText("data.json", json);
}
[Benchmark]
public void DeserializeJson()
{
var json = File.ReadAllText("JsonDeserialize.json");
JsonConvert.DeserializeObject<CLRModel>(json);
}
[Benchmark]
public void SerializeBinary()
{
var model = this.CreateClrModel();
using (var writer = new BinaryWriter(new FileStream("binaryData.dat", FileMode.CreateNew)))
{
writer.Write(model.Money);
writer.Write(model.Name);
writer.Write(model.PageSize);
writer.Write(model.Query);
writer.Write(model.ResultsPerPage);
writer.Flush();
}
}
[Benchmark]
public void DeserializeBinary()
{
var model = new CLRModel();
using (var reader = new BinaryReader(new FileStream("binarydeserialize.dat", FileMode.Open)))
{
model.Money = reader.ReadDecimal();
model.Name = reader.ReadString();
model.PageSize = reader.ReadInt32();
model.Query = reader.ReadString();
model.ResultsPerPage = reader.ReadInt32();
}
}
private HelloRequest CreateProtoModel()
{
return new HelloRequest
{
Money = 526.251,
Name = _Name,
PageNumber = 562,
Query = "SELEcT * FROM dbo.FooBar",
ResultsPerPage = 60,
};
}
private CLRModel CreateClrModel()
{
return new CLRModel
{
Money = 526.251M,
Name = _Name,
PageSize = 60,
Query = "SELEcT * FROM dbo.FooBar",
ResultsPerPage = 60,
};
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace AComms.Client
{
public class CLRModel
{
public string Name { get; set; }
public string Query { get; set; }
public decimal Money { get; set; }
public int PageSize { get; set; }
public int ResultsPerPage { get; set; }
}
}
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: protos/BenchmarkModels.proto
#pragma warning disable 1591, 0612, 3021
#region Designer generated code
using pb = global::Google.Protobuf;
using pbc = global::Google.Protobuf.Collections;
using pbr = global::Google.Protobuf.Reflection;
using scg = global::System.Collections.Generic;
namespace BenchmarkModels {
/// <summary>Holder for reflection information generated from protos/BenchmarkModels.proto</summary>
public static partial class BenchmarkModelsReflection {
#region Descriptor
/// <summary>File descriptor for protos/BenchmarkModels.proto</summary>
public static pbr::FileDescriptor Descriptor {
get { return descriptor; }
}
private static pbr::FileDescriptor descriptor;
static BenchmarkModelsReflection() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
"Chxwcm90b3MvQmVuY2htYXJrTW9kZWxzLnByb3RvEg9CZW5jaG1hcmtNb2Rl",
"bHMiaQoMSGVsbG9SZXF1ZXN0EgwKBE5hbWUYASABKAkSEwoLcGFnZV9udW1i",
"ZXIYAiABKAUSGAoQcmVzdWx0c19wZXJfcGFnZRgDIAEoBRINCgVxdWVyeRgE",
"IAEoCRINCgVtb25leRgFIAEoAWIGcHJvdG8z"));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { },
new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
new pbr::GeneratedClrTypeInfo(typeof(global::BenchmarkModels.HelloRequest), global::BenchmarkModels.HelloRequest.Parser, new[]{ "Name", "PageNumber", "ResultsPerPage", "Query", "Money" }, null, null, null)
}));
}
#endregion
}
#region Messages
/// <summary>
/// The request message
/// </summary>
public sealed partial class HelloRequest : pb::IMessage<HelloRequest> {
private static readonly pb::MessageParser<HelloRequest> _parser = new pb::MessageParser<HelloRequest>(() => new HelloRequest());
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<HelloRequest> Parser { get { return _parser; } }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pbr::MessageDescriptor Descriptor {
get { return global::BenchmarkModels.BenchmarkModelsReflection.Descriptor.MessageTypes[0]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public HelloRequest() {
OnConstruction();
}
partial void OnConstruction();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public HelloRequest(HelloRequest other) : this() {
name_ = other.name_;
pageNumber_ = other.pageNumber_;
resultsPerPage_ = other.resultsPerPage_;
query_ = other.query_;
money_ = other.money_;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public HelloRequest Clone() {
return new HelloRequest(this);
}
/// <summary>Field number for the "Name" field.</summary>
public const int NameFieldNumber = 1;
private string name_ = "";
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public string Name {
get { return name_; }
set {
name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
}
/// <summary>Field number for the "page_number" field.</summary>
public const int PageNumberFieldNumber = 2;
private int pageNumber_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int PageNumber {
get { return pageNumber_; }
set {
pageNumber_ = value;
}
}
/// <summary>Field number for the "results_per_page" field.</summary>
public const int ResultsPerPageFieldNumber = 3;
private int resultsPerPage_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int ResultsPerPage {
get { return resultsPerPage_; }
set {
resultsPerPage_ = value;
}
}
/// <summary>Field number for the "query" field.</summary>
public const int QueryFieldNumber = 4;
private string query_ = "";
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public string Query {
get { return query_; }
set {
query_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
}
/// <summary>Field number for the "money" field.</summary>
public const int MoneyFieldNumber = 5;
private double money_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public double Money {
get { return money_; }
set {
money_ = value;
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) {
return Equals(other as HelloRequest);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool Equals(HelloRequest other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (Name != other.Name) return false;
if (PageNumber != other.PageNumber) return false;
if (ResultsPerPage != other.ResultsPerPage) return false;
if (Query != other.Query) return false;
if (Money != other.Money) return false;
return true;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
if (Name.Length != 0) hash ^= Name.GetHashCode();
if (PageNumber != 0) hash ^= PageNumber.GetHashCode();
if (ResultsPerPage != 0) hash ^= ResultsPerPage.GetHashCode();
if (Query.Length != 0) hash ^= Query.GetHashCode();
if (Money != 0D) hash ^= Money.GetHashCode();
return hash;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void WriteTo(pb::CodedOutputStream output) {
if (Name.Length != 0) {
output.WriteRawTag(10);
output.WriteString(Name);
}
if (PageNumber != 0) {
output.WriteRawTag(16);
output.WriteInt32(PageNumber);
}
if (ResultsPerPage != 0) {
output.WriteRawTag(24);
output.WriteInt32(ResultsPerPage);
}
if (Query.Length != 0) {
output.WriteRawTag(34);
output.WriteString(Query);
}
if (Money != 0D) {
output.WriteRawTag(41);
output.WriteDouble(Money);
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CalculateSize() {
int size = 0;
if (Name.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
}
if (PageNumber != 0) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(PageNumber);
}
if (ResultsPerPage != 0) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(ResultsPerPage);
}
if (Query.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Query);
}
if (Money != 0D) {
size += 1 + 8;
}
return size;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(HelloRequest other) {
if (other == null) {
return;
}
if (other.Name.Length != 0) {
Name = other.Name;
}
if (other.PageNumber != 0) {
PageNumber = other.PageNumber;
}
if (other.ResultsPerPage != 0) {
ResultsPerPage = other.ResultsPerPage;
}
if (other.Query.Length != 0) {
Query = other.Query;
}
if (other.Money != 0D) {
Money = other.Money;
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(pb::CodedInputStream input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
input.SkipLastField();
break;
case 10: {
Name = input.ReadString();
break;
}
case 16: {
PageNumber = input.ReadInt32();
break;
}
case 24: {
ResultsPerPage = input.ReadInt32();
break;
}
case 34: {
Query = input.ReadString();
break;
}
case 41: {
Money = input.ReadDouble();
break;
}
}
}
}
}
#endregion
}
#endregion Designer generated code
syntax = "proto3";
package BenchmarkModels;
// The request message
message HelloRequest {
string Name = 1;
int32 page_number = 2;
int32 results_per_page = 3;
string query = 4;
double money = 5;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment