Top 5 Fastest WCF Serializers

Recently have been using WCF again at work, I wondered how slow (or fast) the latest DataContractSerailizer is. I was pleasantly surprised that it was fairly similar in speed to the JSon Serializer.

Time-100k

Memoryusage-100k

I have run some benchmarks and run speed tests on the following 5 serializers:

DataContractSerializer

This is the default WCF serializer and is used by specifying the DataContract and DataMember attributes on your classes such as the following:

[DataContract]
public class DtoDataContract : IDataContract
{
    [DataMember]
    public long Id { get; set; }

    [DataMember]
    public string Name { get; set; }

    [DataMember]
    public string Description { get; set; }

    // Other Members
}

This generates XML with each Class and Field as Tags, such as the following:

<DtoDataContract i:type="ArrayOfDtoDataContract" xmlns="http://schemas.datacontract.org/2004/07/Benchmark" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <DtoDataContract>
        <Balance>736.13</Balance>
        <Created>2017-02-22T09:04:29.0656576+00:00</Created>
        <Description>Open-architected responsive service-desk</Description>
        <Id>0</Id>
        <Interest>506.00</Interest>
        <Limit>230.27</Limit>
        <Name>Bernier Group</Name>
        <Transaction>260.22</Transaction>
    </DtoDataContract>
</DtoDataContract>

Size: 473 Bytes

NetDataContractSerializer

This is an alternative Serializer that comes out of the box with WCF, and it is very similar to DataContractSerializer but adds additional information to each tag that can be used by the client.

This serializer generates the following output:

<ArrayOfDtoDataContract z:Id="1" z:Type="System.Collections.Generic.List`1[[Benchmark.DtoDataContract, Benchmark, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]" z:Assembly="0" xmlns="http://schemas.datacontract.org/2004/07/Benchmark" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">
    <_items z:Id="2" z:Size="4">
        <DtoDataContract z:Id="3">
            <Balance>736.13</Balance>
            <Created>2017-02-22T09:04:29.0656576+00:00</Created>
            <Description z:Id="4">Open-architected responsive service-desk</Description>
            <Id>0</Id>
            <Interest>506.00</Interest>
            <Limit>230.27</Limit>
            <Name z:Id="5">Bernier Group</Name>
            <Transaction>260.22</Transaction>
        </DtoDataContract>
        <DtoDataContract i:nil="true" />
        <DtoDataContract i:nil="true" />
        <DtoDataContract i:nil="true" />
    </_items>
    <_size>1</_size>
    <_version>1</_version>
</ArrayOfDtoDataContract>

Size: 874 Bytes

Newtonsoft.JSON

[  
   {  
      "Id":0,
      "Name":"Bernier Group",
      "Description":"Open-architected responsive service-desk",
      "Created":"2017-02-22T09:04:29.0656576+00:00",
      "Balance":736.13,
      "Transaction":260.22,
      "Interest":506.00,
      "Limit":230.27
   }
]

Size: 207 Bytes

ProtoBuf

I decided to compare Google ProtocalBuffers .NET implementation by Marc Gravell – protobufnet.

To use ProtoBuf, you need to decorate the class with ProtoContract and each member with ProtoMember(x) where x is the position of the field when serializing.

[ProtoContract]
public class DtoDataContract : IDataContract
{
    [ProtoMember(1)]
    public long Id { get; set; }

    [ProtoMember(2)]
    public string Name { get; set; }

    [ProtoMember(3)]
    public string Description { get; set; }

    // Other members
}

Result is Raw Binary Stream such as:

f\u0012
Bernier Group\u001a(Open-architected responsive service-desk"\u000b\u0008�Ũ����4\u0010\u0005*\u0006\u0008��\u0004\u0018\u00042\u0006\u0008��\u0001\u0018\u0004:\u0006\u0008��\u0003\u0018\u0004B\u0006\u0008�\u0001\u0018\u0004

Size: 104 B

BinaryWriter

This is a custom hand rolled BinaryWriter for my class using BinaryWriter and BinaryReader such as the following:

Serializing

// Count of items in list to help deserialize
writer.Write(_items.Count);

foreach (var item in _items)
{
    writer.Write(item.Id);
    writer.Write(item.Balance);
    writer.Write(item.Description);
    writer.Write(item.Interest);
    writer.Write(item.Transaction);
    writer.Write(item.Limit);
    writer.Write(item.Name);
    writer.Write(item.Created.ToBinary());
}

Deserializing

var reader = new BinaryReader(stream);

var count = reader.ReadInt32();
var list = new List<DtoDataContract>(count);

while (stream.Position < stream.Length)
{
    var item = new DtoDataContract
    {
        Id = reader.ReadInt64(),
        Balance = reader.ReadDecimal(),
        Description = reader.ReadString(),
        Interest = reader.ReadDecimal(),
        Transaction = reader.ReadDecimal(),
        Limit = reader.ReadDecimal(),
        Name = reader.ReadString(),
        Created = DateTime.FromBinary(reader.ReadInt64())
    };

    list.Add(item);
}

This produces a 30% longer binary stream than protobuf (surprisingly) but is faster

\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000�\u001f\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0002\u0000(Open-architected responsive service-desk��\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0002\u0000�e\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0002\u0000�Y\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0002\u0000

Size: 139 B

NuGet – Find Project referencing Version Y of Pkg M – Part 1 of 2

Had an issue at work where Visual Studio Solution (.sln) was constantly showing that a NuGet package can be updated, even though all of the individual projects where up-to date, and greyed out.

I did some digging and had to learn PowerShell in order to find this out, as this can be used in the NuGet Package Manager Console.

First of all you will need to run the Get-Project -All to list all of the projects in the solution.

This returns a List<System.__ComObject> (C# Equivalent)

Finding out properties of an object

To Find out what variables are available in that object, I piped this output into the following commands:

  • | Select-Object -First 1 in order to only get the first object in the list
  • | Select * in order to select all properties of that object.
  • | Write-Host command in order to output all variables

This returned a list of all the available variables in the piped System.__ComObject

E.g. `@{Name=ABC; FullName=C:\SomeDir\SomeSln\ABC.csprod; …..}

Find installed packages using Get-Package command

NuGet has a command called Get-Package which lets you list all installed packages inside a Solution/Project.

It has 2 parameters which will help us:

  • -Filter M Which allows us to filter according to some string. E.g. Get-Package -Filter M to get all the packages with M in its name.
  • -First x which allows us to get the top x number of packages. E.g. Get-Package -First 1
  • -Project ABC Which allows us to filter for installed packages only in the specified project ABC

First I run Get-Package -Filter M to get a list of all the M packages installed.

This returned the following values

Id   Version
---  ------
M    1.0.0.0
M    2.0.0.0

As I am interested only in the older version. I knew I could use -First 1 in order to just get the first value.

Therefore Get-Package -Filter M -First 1 returned only the older package M(1.0.0.0)

Looping through each project

Powershell has a ForEach{} statement which you can use to loop over a collection, such as the List of System.__ComObjects returned from Get-Project -All

E.g. Get-Project | ForEach{ WriteHost }

This will loop over each returned object from Get-Project and do a Console.WriteLine(object). This basically just prints out a System.__ComObject\r\n per project.

There is a shorthand for writing ForEach{} statements in PowerShell which is %{}. Making the following 2 statements identical

Get-Project | ForEach{ Write Host }
Get-Project | %{ Write Host }    

I will use the shorthand %{} ForEach notation from now on.

Accessing the Piped Object

You can access the current piped variable using the $_ notation

Therefore you can access all the properties of this object inside the loop by $_.Property

E.g. Get-Package | %{ $_.Name } will return a list of all Project Names.(As Name is a property on the returned object from Get-Package

To Be Continued

In the next part I will talk about how using all of these, you can find out which project is referencing an older version of a NuGet package.

This should be available by 6th March 2016. Keep tuned in!