29 votes

WCF vs .Net Remoting

selon cet article, WCF avec les canaux nommés est le meilleur choix pour l'IPC, et il est environ 25 % plus rapide que .Net Remoting.

J'ai le code suivant qui compare WCF avec des canaux nommés avec .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;
    }
}

Un a obtenu les résultats suivants pour 5000 itérations:

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

Wcf est environ 7 fois plus lent que .Net Remoting dans ce test.

J'ai essayé de:

  • définir le mode de sécurité à None;
  • définir la InstanceContextMode Unique/PerCall;
  • définir la ConcurrencyMode Unique/Multiple;

mais le résultat est le même.

Quelqu'un sait ce que je fais mal? Pourquoi WCF est-elle si lente?

Est-il un moyen d'accélérer ce code?

Merci à l'avance.

EDIT:

J'ai modifié le tester un peu. Le contrat est le même.

Le premier test ressemble à ceci (test 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);
    }
}

Voici les résultats:

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

Le deuxième test ressemble à ceci (.Net Remoting test):

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

Voici les résultats:

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

Comme vous pouvez le voir, .Net Remoting est plus rapide encore. Les tests ont été effectuées en dehors du débogueur.

Pourquoi est-ce donc?

23voto

Surjit Samra Points 2797

Les débogueurs ne sont pas une vraie mesure lorsque j'essaie de comparer les performances, voici ce que j'ai fait et obtenu WCF Kicking out Remoting de l'anneau;)

1) A également modifié votre test pour l'exécuter à partir du même programme / 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) Compilez-le en mode release et exécutez-le en dehors du débogueur.

voici ma sortie entrez la description de l'image ici

11voto

Tad Donaghe Points 5331

Si, en plus du code de SSamra, vous déplacez la création de votre hôte en dehors de votre test WCF (car, à mon avis, vous ne devez créer l'hôte qu'une seule fois), vous pouvez obtenir des réponses encore plus rapides:

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

Réponses: entrez la description de l'image ici

Cela montre que, lorsqu'il est configuré comme ceci, WCF en cours est beaucoup plus rapide que la communication à distance .Net!

5voto

Chris Dickson Points 8066

L'article MSDN vous référer au début de votre question compare Remoting avec WCF NetNamedPipes comme un IPC mécanisme (le sens de la Communication Inter-Processus, et non Intra-Process Communication). Votre code de test est de comparer les performances de communication au sein du même processus.

C'est ma compréhension que WCF designers avait un but de la quasi-battre toutes les pré-existantes, les technologies de communication à distance pour la performance, dans tous les inter-réseau et de la croix-processus de scénarios, mais pas nécessairement de la croix-domaine dans le même processus. En fait je pense qu'ils ont obtenu assez proche de l'accès distant performance dans le cross-domain scénario trop, comme d'autres answerers ont indiqué. Mais vous ne devriez pas être surpris si vous n'obtenez pas un gain de performance de l'aide de la WCF dans ce scénario particulier.

Ce n'est pas une raison de douter de la WCF des performances supérieures pour la Communication Inter-Processus.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X