我的测试表明 .NET 远程处理比 WCF 4 快 1.5 倍

My test indicates .NET Remoting is faster than WCF 4 by a factor of 1.5

提问人:Gqqnbig 提问时间:2/10/2012 最后编辑:Gqqnbig 更新时间:8/29/2013 访问量:1395

问:

为了判断我的项目是否应该从 .net 远程处理迁移到 WCF,我提取了它的网络通信部分,并通过 WCF 实现了它。我运行了远程处理版本和 wcf 版本,最终发现远程处理比 wcf 快 1.5 倍,这与 msdn 文章有很大不同。

测试配置

WCF 和 .NET 远程处理都使用不带加密的 tcp 通道,不带 app.config 文件。以发布模式编译,无优化。

操作

我的程序是这样做的。sequence diagram

您可以在此处下载这两种解决方案。

WCF 测试

服务主机

    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();

服务器

[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);
    }
}

客户端

    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 是一张大小为139KB的图片。

玩家等级

[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 远程处理测试

主机

    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);

客户

    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();

您可以在此处下载这两种解决方案。

结果

enter image description here

那么,我是否在对 WCF 不公平的地方进行测试?

WCF 性能 比较 处理 .net-remoting

评论

0赞 Chris Holwerda 7/16/2013
远程处理已弃用。这是让您的申请按计划提升的最大原因 - msdn.microsoft.com/en-us/library/kwdt6w2k%28v=VS.100%29.aspx
0赞 Gqqnbig 7/24/2013
无论如何。远程处理速度很快,WCF 有一些远程处理没有的限制。现在,我的一个应用程序正在使用远程处理。
0赞 AnthonyVO 10/26/2014
在我能从 WCF 中挤出相同的性能之前,我还将继续将 .net Remoting 保留在我的工具箱中。
0赞 Artemix 11/12/2014
是调试还是发布?在这个答案中,发布版本似乎解决了这个问题。
0赞 Gqqnbig 11/13/2014
“在发布模式下编译”

答:

0赞 Rom Eh 8/9/2013 #1

应该是消息编码王吗?

您是否使用过 binaryMessageEncoding 而不是 textMessageEncoding 或 soapMessageEncoding ?

您可以创建自定义绑定来执行此操作:

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;
    }
}

评论

0赞 Gqqnbig 8/18/2013
你在哪里找到我使用的是 textMessageEncoding 或 soapMessageEncoding?
0赞 Rom Eh 8/29/2013
可以创建自定义绑定(通过扩展类 CustomBinding (System.ServiceModel.Channels))。