7

In order to tell whether my project should migrate from .net remoting to WCF, I extracted its network communication part and implemented it by WCF. I run the remoting version and wcf version and eventually find remoting is faster than wcf by a factor of 1.5, which greatly differs from the msdn article.

Test configuration

WCF and .NET Remoting both use tcp channel without encryption, no app.config file. Compiled in release mode, no optimization.

Operations

What my program does is this. sequence diagram

You can download the two solutions here.

WCF test

Service Host

    ServiceHost host = new ServiceHost(typeof(Server), new Uri(string.Format("net.tcp://{0}:{1}/{2}", args[0], args[1], args[2])));
    var binding = new NetTcpBinding();
    binding.MaxReceivedMessageSize = 614400;
    binding.ReaderQuotas.MaxArrayLength = 512000;//a max picture of 500KB
    binding.Security.Mode = SecurityMode.None;
    host.AddServiceEndpoint(typeof(IServer), binding, string.Empty);
    host.Open();

Server

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single
    //, IncludeExceptionDetailInFaults = true
    , ConcurrencyMode = ConcurrencyMode.Reentrant
    )]
public class Server : IServer
{
    public EntryRequirement GetEntryRequirement()
    {
        return new EntryRequirement(new[] { "fuck", "sex" }, false);
    }

    public void AddClient()
    {
        var client = OperationContext.Current.GetCallbackChannel<IServerCallback>();
        var p = client.Profile;
        var x = client.Password;
        System.Diagnostics.Debug.WriteLine(p);
        System.Diagnostics.Debug.WriteLine(x);
    }
}

Client side

    Player player = new Player();
    player.Password = "12423";
    player.Profile = new Contracts.PlayerProfile
                         {
                             Description = "I'm a man.",
                             HeadImage = imageData,
                             Name = "Loveright"
                         };


    var binding = new NetTcpBinding();
    binding.Security.Mode = SecurityMode.None;
    Stopwatch watch = new Stopwatch();
    watch.Start();
    for (int i = 0; i < 20; i++)
    {
        ServerProxy server = new ServerProxy(player, binding, 
            new EndpointAddress(string.Format("net.tcp://{0}:{1}/{2}", args[0], args[1], args[2])));
        server.GetEntryRequirement();
        server.AddClient();
    }

    watch.Stop();

HeadImage is a picture of size 139KB.

Player class

[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
class Player : IServerCallback
{
    public PlayerProfile Profile { get; set; }

    public string Password { get; set; }

    public void ClientCollectionChangedEventHandler(object sender, ControllersChangedEventArgs e)
    {

    }

    public void ClientUpdatedEventHandler(object sender, ClientUpdatedEventArgs e)
    {

    }
}

.NET Remoting test

Host

    var serverProv = new BinaryServerFormatterSinkProvider();
    serverProv.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
    var clientProv = new BinaryClientFormatterSinkProvider();
    IDictionary props = new Hashtable();
    props["port"] = args[1];
    props["name"] = "tcp server";
    var channel = new TcpChannel(props, clientProv, serverProv);

    ChannelServices.RegisterChannel(channel, false);

    System.Runtime.Remoting.RemotingConfiguration.RegisterWellKnownServiceType(typeof(Server),
                                args[2], System.Runtime.Remoting.WellKnownObjectMode.Singleton);

Client

    var serverProv = new BinaryServerFormatterSinkProvider();
    serverProv.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
    var clientProv = new BinaryClientFormatterSinkProvider();
    IDictionary props = new Hashtable();
    props["name"] = "tcp client " + Guid.NewGuid();
    props["port"] = 0;

    var channel = new TcpChannel(props, clientProv, serverProv);
    ChannelServices.RegisterChannel(channel, false);

    FileStream stream = new FileStream(@"logotz6.png", FileMode.Open);
    byte[] imageData = new byte[stream.Length];
    stream.Read(imageData, 0, imageData.Length);
    stream.Close();
    Player player = new Player();
    player.Password = "12423";
    player.Profile = new PlayerProfile
    {
        Description = "I'm a man.",
        HeadImage = imageData,
        Name = "Loveright"
    };

    Stopwatch watch = new Stopwatch();
    watch.Start();
    for (int i = 0; i < 20; i++)
    {
        var serverProxy = (IServer)Activator.GetObject(typeof(IServer), string.Format("tcp://{0}:{1}/{2}", args[0], args[1], args[2]));
        serverProxy.GetEntryRequirement();
        serverProxy.AddClient(player);
    }
    watch.Stop();

You can download the two solutions here.

Result

enter image description here

So do I make the test somewhere unfair to WCF?

Gqqnbig
  • 5,845
  • 10
  • 45
  • 86
  • Remoting is deprecated. That is the biggest reason for getting your application on an uplift schedule - http://msdn.microsoft.com/en-us/library/kwdt6w2k%28v=VS.100%29.aspx – Chris Holwerda Jul 15 '13 at 19:52
  • Anyway. Remoting is fast and WCF has some limitations that remoting doesn't have. Now one of my application is using remoting. – Gqqnbig Jul 24 '13 at 00:36
  • Until I can squeeze the same performance out of WCF, I will also continue to keep .net Remoting in my toolbox. – AnthonyVO Oct 25 '14 at 17:31
  • Was it Debug or Release bulid? In this [answer](http://stackoverflow.com/a/8056809/694852) the Release build seems to fix the issue. – Artemix Nov 12 '14 at 13:56
  • "Compiled in release mode" – Gqqnbig Nov 12 '14 at 23:05

1 Answers1

0

Should it be the message encoding king ?

Have you used binaryMessageEncoding instead of textMessageEncoding or soapMessageEncoding ?

You can create a custom binding to do this :

internal sealed class MyBinding : CustomBinding
{
    private static readonly BindingElementCollection elementCollection;

    static MyBinding()
    {
        MessageEncodingBindingElement encoding = new BinaryMessageEncodingBindingElement();

        TcpTransportBindingElement transport = new TcpTransportBindingElement();

        elementCollection = new BindingElementCollection();
        elementCollection.Add(encoding);
        elementCollection.Add(transport);
    }

    internal MyBinding(string bindingName, string bindingNamespace)
        : base()
    {
        base.Namespace = bindingNamespace;
        base.Name = bindingName;
    }

    public override BindingElementCollection CreateBindingElements()
    {
        return elementCollection;
    }
}
Rom Eh
  • 1,981
  • 1
  • 16
  • 33