【问题标题】:WCF vs. .Net RemotingWCF 与 .Net 远程处理
【发布时间】:2011-12-24 17:29:49
【问题描述】:

根据this article,带有命名管道的 WCF 是 IPC 的最佳选择,它比 .Net Remoting 快约 25%。

我有以下代码将 WCF 与命名管道与 .Net Remoting 进行比较:

[ServiceContract]
internal interface IRemote
{
    [OperationContract]
    string Hello(string name);
}

[ServiceBehavior]
internal class Remote : MarshalByRefObject, IRemote
{
    public string Hello(string name)
    {
        return string.Format("Hello, {0}!", name);
    }
}

class Program
{
    private const int Iterations = 5000;

    static void Main(string[] args)
    {
        TestWcf(Iterations);
        TestRemoting(Iterations);

        TestWcf(Iterations);
        TestRemoting(Iterations);

        TestWcf(Iterations);
        TestRemoting(Iterations);

        Console.ReadKey();
    }

    private static void TestRemoting(int iterations)
    {
        var domain = AppDomain.CreateDomain("TestDomain");

        var proxy =
            (IRemote)
            domain.CreateInstanceFromAndUnwrap(Assembly.GetEntryAssembly().Location, "ConsoleApplication6.Remote");

        Console.WriteLine("Remoting: {0} ms.", Test(proxy, iterations));
    }

    private static void TestWcf(int iterations)
    {
        var address = "net.pipe://localhost/test";

        var host = new ServiceHost(typeof (Remote));
        host.AddServiceEndpoint(typeof (IRemote), new NetNamedPipeBinding(), address);
        host.Open();

        var proxy = ChannelFactory<IRemote>.CreateChannel(new NetNamedPipeBinding(), new EndpointAddress(address));

        Console.WriteLine("Wcf: {0} ms.", Test(proxy, iterations));

        host.Close();
    }

    private static double Test(IRemote proxy, int iterations)
    {
        var start = DateTime.Now;

        for (var i = 0; i < iterations; i++)
        {
            proxy.Hello("Sergey");
        }

        var stop = DateTime.Now;

        return (stop - start).TotalMilliseconds;
    }
}

A 在 5000 次迭代中得到以下结果:

Wcf: 14143 ms.
Remoting: 2232 ms.
Wcf: 14289 ms.
Remoting: 2130 ms.
Wcf: 14126 ms.
Remoting: 2112 ms.

在此测试中,Wcf 比 .Net Remoting 慢 7 倍左右。

我尝试过:

  • 将安全模式设置为无;
  • 将 InstanceContextMode 设置为 Single/PerCall;
  • 将 ConcurrencyMode 设置为 Single/Multiple;

但结果是一样的。

有人知道我做错了什么吗?为什么 WCF 这么慢?

有没有办法加快这段代码的速度?

提前致谢。

编辑:

我稍微修改了测试。合同是一样的。

第一个测试看起来像这样(Wcf 测试):

class Program
{
    private const int Iterations = 5000;

    static void Main(string[] args)
    {
        var address = "net.pipe://localhost/test";

        var host = new ServiceHost(typeof(Remote));
        host.AddServiceEndpoint(typeof(IRemote), new NetNamedPipeBinding(NetNamedPipeSecurityMode.None), address);
        host.Open();

        var proxy = ChannelFactory<IRemote>.CreateChannel(new NetNamedPipeBinding(NetNamedPipeSecurityMode.None), new EndpointAddress(address));

        TestWcf(proxy, Iterations);
        TestWcf(proxy, Iterations);
        TestWcf(proxy, Iterations);
        TestWcf(proxy, Iterations);
        TestWcf(proxy, Iterations);

        Console.ReadKey();

        host.Close();
    }

    private static void TestWcf(IRemote proxy, int iterations)
    {
        var start = DateTime.Now;

        for (var i = 0; i < iterations; i++)
        {
            proxy.Hello("Sergey");
        }

        var stop = DateTime.Now;

        Console.WriteLine("Wcf: {0} ms.", (stop - start).TotalMilliseconds);
    }
}

结果如下:

Wcf: 2564 ms.
Wcf: 1026 ms.
Wcf: 986 ms.
Wcf: 990 ms.
Wcf: 992 ms.

第二个测试看起来像这样(.Net Remoting 测试):

class Program
{
    private const int Iterations = 5000;

    static void Main(string[] args)
    {
        var domain = AppDomain.CreateDomain("TestDomain");

        var proxy =
            (IRemote)
            domain.CreateInstanceFromAndUnwrap(Assembly.GetEntryAssembly().Location, "ConsoleApplication6.Remote");

        TestRemoting(proxy, Iterations);
        TestRemoting(proxy, Iterations);
        TestRemoting(proxy, Iterations);
        TestRemoting(proxy, Iterations);
        TestRemoting(proxy, Iterations);

        Console.ReadKey();
    }

    private static void TestRemoting(IRemote proxy, int iterations)
    {
        var start = DateTime.Now;

        for (var i = 0; i < iterations; i++)
        {
            proxy.Hello("Sergey");
        }

        var stop = DateTime.Now;

        Console.WriteLine("Remoting: {0} ms.", (stop - start).TotalMilliseconds);
    }
}

结果如下:

Remoting: 261 ms.
Remoting: 224 ms.
Remoting: 252 ms.
Remoting: 243 ms.
Remoting: 234 ms.

如您所见,.Net Remoting 再次变得更快。测试在调试器之外运行。

为什么会这样?

【问题讨论】:

  • 你能提供你的配置文件吗?
  • villecoder:我不使用配置。绑定、端点、行为在代码中设置。

标签: c# wcf named-pipes .net-remoting


【解决方案1】:

调试器在尝试比较性能时并不是真正的衡量标准,这就是我所做的并让 WCF 从环中踢出远程;)

1) 还修改了您的测试以从相同的程序/exe 运行它

  namespace ConsoleApplication6
{
  [ServiceContract]
  internal interface IRemote
  {
    [OperationContract]
    string Hello(string name);
  }

  [ServiceBehavior]
  internal class Remote : MarshalByRefObject, IRemote
  {
    public string Hello(string name)
    {
      return string.Format("Hello, {0}!", name);
    }
  }

  class Program
  {
    private const int Iterations = 5000;

    static void Main(string[] p)
    {
      TestWcf();
      TestRemoting();
    }


    static void TestWcf()
    {
      var address = "net.pipe://localhost/test";

      var host = new ServiceHost(typeof(Remote));
      host.AddServiceEndpoint(typeof(IRemote), new NetNamedPipeBinding(NetNamedPipeSecurityMode.None), address);
      host.Open();

      var proxy = ChannelFactory<IRemote>.CreateChannel(new NetNamedPipeBinding(NetNamedPipeSecurityMode.None), new EndpointAddress(address));

      TestWcf(proxy, Iterations);
      TestWcf(proxy, Iterations);
      TestWcf(proxy, Iterations);
      TestWcf(proxy, Iterations);
      TestWcf(proxy, Iterations);

      Console.WriteLine("WCF done");

      host.Close();
    }

    private static void TestWcf(IRemote proxy, int iterations)
    {
      var start = DateTime.Now;

      for (var i = 0; i < iterations; i++)
      {
        proxy.Hello("Sergey");
      }

      var stop = DateTime.Now;

      Console.WriteLine("Wcf: {0} ms.", (stop - start).TotalMilliseconds);
    }

    static void TestRemoting()
    {
      var domain = AppDomain.CreateDomain("TestDomain");

      var proxy =
          (IRemote)
          domain.CreateInstanceFromAndUnwrap(Assembly.GetEntryAssembly().Location, "ConsoleApplication6.Remote");

      TestRemoting(proxy, Iterations);
      TestRemoting(proxy, Iterations);
      TestRemoting(proxy, Iterations);
      TestRemoting(proxy, Iterations);
      TestRemoting(proxy, Iterations);
      Console.WriteLine("Remoting done");
      Console.ReadKey();
    }

    private static void TestRemoting(IRemote proxy, int iterations)
    {
      var start = DateTime.Now;

      for (var i = 0; i < iterations; i++)
      {
        proxy.Hello("Sergey");
      }

      var stop = DateTime.Now;

      Console.WriteLine("Remoting: {0} ms.", (stop - start).TotalMilliseconds);
    }
  }

}

2) 在发布模式下编译并在调试器外部运行。

这是我的输出

【讨论】:

  • 感谢您的评论。它确实在调试器之外运行得更快。
  • 我还从我之前的一个 SO 线程中意识到,如果将 Build Type 设置为 Release,性能也会得到提升
【解决方案2】:

如果除了 SSamra 的代码之外,您将主机的创建移到 WCF 测试之外(因为在我看来,您应该只创建一次主机),您可以获得更快的响应:

static void Main(string[] args)
{
    var address = "net.pipe://localhost/test";

    host = new ServiceHost(typeof(Remote));
    host.AddServiceEndpoint(typeof(IRemote), new NetNamedPipeBinding(NetNamedPipeSecurityMode.None), address);
    host.Open();

    proxy = ChannelFactory<IRemote>.CreateChannel(new NetNamedPipeBinding(NetNamedPipeSecurityMode.None), new EndpointAddress(address));

    TestWcf(Iterations);
    TestRemoting(Iterations);

    TestWcf(Iterations);
    TestRemoting(Iterations);

    TestWcf(Iterations);
    TestRemoting(Iterations);

    host.Close();

    Console.ReadKey();
}

回应:

这表明,当这样配置时,进程中的 WCF 明显快于 .Net 远程处理!

【讨论】:

  • 如果我也将 Remoting 代理的创建移到主程序中,我会得到几乎相同的响应。
  • 太棒了!但我已经更新了这个问题。请看一看。
【解决方案3】:

您在问题开头引用的 MSDN 文章将 Remoting 与 WCF NetNamedPipes 作为一种 IPC 机制(意思是进程间通信,而不是进程内通信)进行了比较。您的测试代码正在比较同一进程中的通信性能。

据我了解,WCF 的设计者的目标是在所有跨网络和跨进程场景中大幅超越所有现有的远程处理技术,但不一定在同一进程中跨域。事实上,正如其他回答者所指出的那样,我认为他们在跨域场景中的远程处理性能也相当接近。但是,如果在此特定场景中使用 WCF 没有获得性能提升,您应该不会感到惊讶。

没有理由怀疑 WCF 在进程间通信方面的卓越性能。

【讨论】:

  • 我好像 WCF 不是在 appdomains 之间交换数据的最佳选择。
【解决方案4】:
Wcf: 261,03 ms.
Wcf: 247,02 ms.
Wcf: 236,02 ms.
Wcf: 235,02 ms.
Wcf: 236,02 ms.

WCF NetNamedPipeBinding done. Avg : 243,02

Wcf: 508,05 ms.
Wcf: 467,05 ms.
Wcf: 484,05 ms.
Wcf: 458,05 ms.
Wcf: 458,05 ms.

WCF NetTcpBinding done. Avg : 475,05

Remoting: 35,00 ms.
Remoting: 58,01 ms.
Remoting: 35,00 ms.
Remoting: 35,00 ms.
Remoting: 34,00 ms.

Remoting done. Avg : 39,40

【讨论】:

    猜你喜欢
    • 2010-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多