c# wcf named-pipes .net-remoting

c# - WCF vs..Net Remoting



named-pipes .net-remoting (4)

El artículo de MSDN al que se refiere al inicio de su pregunta compara el Remoting con WCF NetNamedPipes como un mecanismo de IPC (es decir, comunicación entre procesos, no comunicación dentro del proceso). Su código de prueba compara el rendimiento para la comunicación dentro del mismo proceso.

Tengo entendido que los diseñadores de WCF tenían el objetivo de superar sustancialmente todas las tecnologías remotas preexistentes para el rendimiento, en todos los escenarios entre redes y entre procesos, pero no necesariamente entre dominios dentro del mismo proceso. De hecho, creo que también se acercaron bastante al rendimiento de Remoting en el escenario de dominios cruzados, como lo han indicado otros contestadores. Pero no debería sorprenderse si no obtiene un aumento en el rendimiento al usar WCF en este escenario particular.

No es motivo para dudar del rendimiento superior de WCF para la comunicación entre procesos.

de acuerdo con este artículo , WCF con canalizaciones con nombre es la mejor opción para IPC, y es aproximadamente un 25% más rápido que .Net Remoting.

Tengo el siguiente código que compara WCF con named pipes con .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 obtuvo los siguientes resultados para 5000 iteraciones:

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

Wcf es aproximadamente 7 veces más lento que .Net Remoting en esta prueba.

Lo intenté:

  • establecer el modo de seguridad a Ninguno;
  • establezca el InstanceContextMode en Single / PerCall;
  • establecer el modo ConcurrencyMode en Single / Multiple;

pero los resultados son los mismos

¿Alguien sabe lo que hago mal? ¿Por qué WCF es tan lento?

¿Hay alguna manera de acelerar este código?

Gracias por adelantado.

EDITAR:

He modificado la prueba un poco. El contrato es el mismo

La primera prueba se ve así (prueba 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); } }

Aquí están los resultados:

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

La segunda prueba se ve así (prueba .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); } }

Aquí están los resultados:

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

Como puede ver, .Net Remoting es más rápido de nuevo. Las pruebas se ejecutaron fuera del depurador.

¿Por qué esto es tan?


Los depuradores no son una medida real cuando trato de comparar el rendimiento, esto es lo que hice y conseguí que WCF lanzara Remoting desde el ring;)

1) También modificó su prueba para ejecutarlo desde el mismo programa / 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) Compilarlo en modo de lanzamiento y ejecutarlo fuera del depurador.

aquí está mi salida


Si, además del código SSamra, mueves la creación de tu host fuera de tu prueba WCF (ya que, en mi opinión, solo deberías crear el host una sola vez) puedes obtener respuestas incluso más rápidas:

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

Respuestas

Esto muestra que, cuando se configura así, WCF en proceso es significativamente más rápido que .Net remoto.


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