29 Stimmen

WCF vs. .Net Remoting

Laut diesem Artikel ist WCF mit benannten Pipes die beste Wahl für IPC und etwa 25 % schneller als .Net Remoting.

Ich habe den folgenden Code, der WCF mit benannten Pipes mit .Net Remoting vergleicht:

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

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

class Program
{
    private const int Iterationen = 5000;

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

        TestWcf(Iterationen);
        TestRemoting(Iterationen);

        TestWcf(Iterationen);
        TestRemoting(Iterationen);

        Console.ReadKey();
    }

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

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

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

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

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

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

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

        host.Close();
    }

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

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

        var stop = DateTime.Now;

        return (stop - start).TotalMilliseconds;
    }
}

Die Ergebnisse für 5000 Iterationen lauten wie folgt:

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

In diesem Test ist WCF etwa 7 mal langsamer als .Net Remoting.

Ich habe versucht:

  • den Sicherheitsmodus auf None zu setzen;
  • den InstanceContextMode auf Single/PerCall zu setzen;
  • den ConcurrencyMode auf Single/Multiple zu setzen;

aber die Ergebnisse sind die gleichen.

Weiß jemand, was ich falsch mache? Warum ist WCF so langsam?

Gibt es eine Möglichkeit, diesen Code zu beschleunigen?

Vielen Dank im Voraus.

EDIT:

Ich habe den Test etwas modifiziert. Der Vertrag ist der gleiche.

Der erste Test sieht so aus (Wcf-Test):

class Program
{
    private const int Iterationen = 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.CreateChannel(new NetNamedPipeBinding(NetNamedPipeSecurityMode.None), new EndpointAddress(address));

        TestWcf(proxy, Iterationen);
        TestWcf(proxy, Iterationen);
        TestWcf(proxy, Iterationen);
        TestWcf(proxy, Iterationen);
        TestWcf(proxy, Iterationen);

        Console.ReadKey();

        host.Close();
    }

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

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

        var stop = DateTime.Now;

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

Hier sind die Ergebnisse:

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

Der zweite Test sieht so aus (.Net Remoting-Test):

class Program
{
    private const int Iterationen = 5000;

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

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

        TestRemoting(proxy, Iterationen);
        TestRemoting(proxy, Iterationen);
        TestRemoting(proxy, Iterationen);
        TestRemoting(proxy, Iterationen);
        TestRemoting(proxy, Iterationen);

        Console.ReadKey();
    }

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

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

        var stop = DateTime.Now;

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

Hier sind die Ergebnisse:

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

Wie Sie sehen können, ist .Net Remoting wieder schneller. Die Tests wurden außerhalb des Debuggers durchgeführt.

Warum ist das so?

24voto

Surjit Samra Punkte 4178

Debugger sind kein echtes Maß, wenn man die Leistung vergleichen will. Hier ist, was ich gemacht habe und habe WCF aus dem Ring gekickt ;)

1) Habe auch deinen Test geändert, um ihn vom selben Programm/Exe auszuführen

  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("Hallo, {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.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 erledigt");

      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 erledigt");
      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) Kompilieren Sie es im Release-Modus und führen Sie es außerhalb des Debuggers aus.

hier ist mein Output Bildbeschreibung hier eingeben

11voto

Tad Donaghe Punkte 6640

Wenn Sie neben SSamras Code auch die Erstellung Ihres Hosts außerhalb Ihres WCF-Tests verschieben (meiner Meinung nach sollten Sie den Host nur einmal erstellen), können Sie noch schnellere Antworten erhalten:

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.CreateChannel(new NetNamedPipeBinding(NetNamedPipeSecurityMode.None), new EndpointAddress(address));

    TestWcf(Iterations);
    TestRemoting(Iterations);

    TestWcf(Iterations);
    TestRemoting(Iterations);

    TestWcf(Iterations);
    TestRemoting(Iterations);

    host.Close();

    Console.ReadKey();
}

Antworten: Bildbeschreibung hier eingeben

Dies zeigt, dass WCF im Prozess, wenn es so konfiguriert ist, signifikant schneller ist als .Net Remoting!

5voto

Chris Dickson Punkte 11634

Der MSDN-Artikel, auf den Sie am Anfang Ihrer Frage verweisen, vergleicht Remoting mit WCF NetNamedPipes als IPC-Mechanismus (was für Interprozesskommunikation steht, nicht für Intraprozesskommunikation). Ihr Testcode vergleicht die Leistung für die Kommunikation innerhalb desselben Prozesses.

Meines Wissens hatten die Designer von WCF das Ziel, alle bestehenden Remoting-Technologien in Bezug auf Leistung in allen netzwerkübergreifenden und prozessübergreifenden Szenarien erheblich zu übertreffen, jedoch nicht unbedingt in unterschiedlichen Domänen innerhalb desselben Prozesses. Tatsächlich denke ich, dass sie in dem Fall der unterschiedlichen Domänen auch recht nahe an der Leistung von Remoting sind, wie es andere Antwortgeber bereits angedeutet haben. Es wäre jedoch nicht überraschend, wenn Sie in diesem speziellen Szenario keinen Leistungsgewinn durch die Verwendung von WCF erzielen.

Dies ist kein Grund, an der überlegenen Leistung von WCF für die Interprozesskommunikation zu zweifeln.

0voto

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X