Wednesday, 23 May 2012

WCF Bindings

Carrying on from an excellent MSDN blog post by Rick Rainey comparing the performance of various WCF bindings here is an example including NetNamePipes and ProtoBuf-Net:

Test results

Original blog post:


Is available via Nuget or its Google project hosting:


If you come across the following exception:

HTTP could not register URL http://+:9001/. Your process does not have access rights to this namespace (see for details).

Either run Visual Studio using “Run as Administrator” or visit the following link for a more complete resolution:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Diagnostics;
using ProtoBuf;
using ProtoBuf.ServiceModel;

namespace BindingTest
public interface ITestService
void Execute(TestData data);

public class TestData
public List<string> Data { get; set; }

public class TestService : ITestService
public void Execute(TestData data)
// empty service implementation

class Program
static void Main(string[] args)
var bindingElements = new BindingElement[] {
new BinaryMessageEncodingBindingElement(),
new ReliableSessionBindingElement(true),
new HttpTransportBindingElement()

var bindings = new Binding[]
new WSHttpBinding() { MaxReceivedMessageSize = Int32.MaxValue },
new NetTcpBinding
Name = "NetTcpBinding (SecurityMode.Message)",
Security = { Mode = SecurityMode.Message },
MaxReceivedMessageSize = Int32.MaxValue
new CustomBinding(bindingElements)
Name = "CustomBinding (HTTP/Binary/ReliableSession(ordered)/NoSecurity"
new NetTcpBinding(),
new NetNamedPipeBinding(NetNamedPipeSecurityMode.Transport),
new NetNamedPipeBinding(NetNamedPipeSecurityMode.None)

var payloadSize = 15000;
var iterations = 5;

OutputTitle(payloadSize, iterations);

// Compare all the bindings in the bindings array.
CompareBindings(bindings, payloadSize, iterations, false);

// Compare all the bindings using protobuf-net
CompareBindings(bindings, payloadSize, iterations, true);


public static void OutputTitle(int payloadSize, int iterations)
Console.WriteLine("Test parameters: {0} byte payload, {1} iterations",

private static void OutputNote()
Console.WriteLine("NOTE: NetNamedPipe is only used for same machine inter process communication");

public static string GenerateRandomStringData(int stringSize)
var r = new Random();
var sb = new StringBuilder(stringSize);
while (sb.Length < stringSize)
sb.Append((char)(r.Next(0, 256)));
return sb.ToString();

public static TestData GenerateTestData(int payloadSize)
const int itemDataSize = 4096;

var data = new TestData {Data = new List<string>()};

int numDataItems = payloadSize / itemDataSize;

for (int item = 0; item < numDataItems; item++)

data.Data.Add(GenerateRandomStringData(payloadSize - (numDataItems * itemDataSize)));

return data;

public static void CompareBindings(Binding[] bindings, int payloadSize, int iterations, bool useProtoBuf)
Console.WriteLine("Using {0} serialisation", useProtoBuf ? "protobuf" : "normal");
var data = GenerateTestData(payloadSize);

foreach (var b in bindings)
// Run the test on this binding.
Stopwatch result = TestBinding(b, data, iterations, useProtoBuf);

// Output the results.
//Console.WriteLine(string.Format("Payload Size: {0}, Iterations: {1}", payloadSize, iterations));
//Console.WriteLine(" Binding Elements:");
//foreach (BindingElement be in b.CreateBindingElements())
// Console.WriteLine(" {0}", be.GetType());
Console.WriteLine(", time: {0} ms", result.ElapsedMilliseconds);
catch (Exception e)
Console.WriteLine("EXCEPTION: {0}", e.Message);

public static Stopwatch TestBinding(Binding binding, TestData data, int iterations, bool useProtoBuf)
var address = GetAddress(binding);

// Start the host using the binding provided
var host = new ServiceHost(typeof(TestService), new Uri(address));
var endpoint = host.AddServiceEndpoint(typeof(ITestService), binding, "");

if (useProtoBuf)
endpoint.Behaviors.Add(new ProtoEndpointBehavior());


var sw = new Stopwatch();

// Create a client proxy using the binding provided
var cf = new ChannelFactory<ITestService>(binding, address);
ITestService proxy = cf.CreateChannel();

// Call the service
for (int count = 0; count < iterations; count++)

// Close the client proxy and host.

return sw;

private static string GetAddress(Binding binding)
var machine = "localhost";
var port = (binding.Scheme == "net.pipe")
? ""
: ":9001";

return string.Concat(binding.Scheme, "://", machine, port, "/", Guid.NewGuid().ToString());


1 comment:

  1. Hi Steven,
    Thanks for your post. I'm also trying to evaluate the performance of protobuf for WCF. I added a line in the Execute() to display the number of elements in data.Data, but I found that data is null in the case of protobuf binding. Am I missing something?

    Thanks in advance,