我的测试表明 .NET Remoting 比 WCF 4 快 1.5 倍

发布于 2025-01-04 10:53:43 字数 5122 浏览 3 评论 0原文

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

测试配置

WCF和.NET Remoting都使用不加密的tcp通道,没有app.config文件。在release模式下编译,没有优化。

操作

我的程序所做的是这样的。 序列图

您可以在这里下载这两个解决方案。

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的图片。

Player 类

[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 测试

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

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

结果

在此处输入图像描述

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

尸血腥色 2025-01-11 10:53:43

它应该是消息编码之王吗?

您是否使用过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;
    }
}

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;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文