2010-11-12 10 views
6

He sufrido una gran decepción y recibí una aplicación que, en determinadas situaciones, es al menos 100 veces más lenta, y tengo que comunicarla a nuestros clientes muy pronto (en cuestión de semanas).¿Alguna ganancia rápida para hacer que .NET remote más rápido en una sola máquina?

A través de un perfil muy simple, he descubierto que el cuello de botella es el uso de .NET Remoting para transferir datos entre un servicio de Windows y el front-end gráfico, ambos ejecutados en la misma máquina.

Microsoft guidelines dicen "Minimizar ida y vuelta y evitar las interfaces hablador": escribir

MyComponent.SaveCustomer("bob", "smith"); 

en lugar de

MyComponent.Firstname = "bob"; 
MyComponent.LastName = "smith"; 
MyComponent.SaveCustomer(); 

Creo que esta es la raíz del problema en nuestra aplicación. Lamentablemente, las llamadas a MyComponent. * (El generador de perfiles muestra que el 99,999% del tiempo se gasta en dichas declaraciones) se reparten libremente a lo largo del código fuente y no veo ninguna esperanza de rediseñar la interfaz de acuerdo con las directrices anteriores.

Editar: De hecho, la mayoría de las veces el front-end lee las propiedades de MyComponent en lugar de escribir en ellas. Pero sospecho que MyComponent puede cambiar en cualquier momento en el back-end.

Miré para ver si puedo leer todas las propiedades de MyComponent de una vez y luego ponerlas en caché localmente (ignorando el problema del cambio en cualquier momento anterior), pero eso implicaría alterar cientos de líneas de código.

Mi pregunta es: ¿Son algunas cosas 'de ganancia rápida' que puedo tratar de mejorar el rendimiento?

Necesito al menos una aceleración de 100 veces. Soy un programador C/C++/Delphi y estoy bastante, muy poco familiarizado con C# /. NET/Remoting que no sea lo que he leído en los últimos días. Estoy buscando cosas que se puedan completar en unos días: una reestructuración importante del código no es una opción.

Solo para empezar, ya he confirmado que está usando BinaryFormatter.

(Lo siento, esto es probablemente una pregunta terribles en la línea de '¿Cómo puedo factiblemente solución X si yo descarto todas las opciones viables' ... pero estoy desesperado!)

Editar 2 en respuesta al comentario de Richard a continuación: Creo que mi pregunta se reduce a:

  1. ¿hay alguna configuración que puede cambiar para reducir el costo de un .NET Remoting de ida y vuelta cuando ambos extremos de la conexión están en el misma máquina?
  2. ¿Hay alguna configuración que pueda cambiar para reducir el número de viajes de ida y vuelta, de modo que cada invocación de una propiedad de objeto remoto no dé lugar a un viaje de ida y vuelta por separado? Y podría esto romper algo?
+1

Es probable que sus opciones sean limitadas, .NET Remoting está muy desaprobado (excepto para el dominio entre aplicaciones) debido a su falta de seguridad. – Richard

+1

"Ganancia rápida" invariable significa "lento perder" en el imho, tenga mucho cuidado con esa frase. – annakata

+0

Si se tratara de WCF, el ["transporte nulo"] (http://www.codeproject.com/KB/WCF/NullTransportForWCF.aspx) podría haber ayudado, pero ese es un modelo muy diferente al de la comunicación remota. –

Respuesta

7

En .Net Remoting tiene 3 formas de comunicarse por HTTP, TCP e IPC. Si commnuicatin está en la misma PC que utilizo para usar canales IPC, acelerará tus llamadas.

+1

¡Gracias! Este es exactamente el tipo de respuesta que esperaba. Resulta que estaba usando HTTP. Una operación que tomó 3 minutos y 20 segundos con HTTP tomó 1 minuto 24 con TCP y 59 segundos con IPC. 59 segundos es todavía demasiado largo (desde la perspectiva del usuario, simplemente está expandiendo un nodo en una vista en árbol, por lo que debe ser instantáneo), pero es una gran mejora. Para el beneficio de cualquier otra persona que intente esto, tuve que especificar authorizedGroup = "Users" en el elemento en el servidor. De lo contrario, era sencillo. –

+0

Estoy haciendo de esto mi 'respuesta aceptada' porque es una verdadera ganancia rápida. De todos modos, aún necesito acelerar el código. –

1

Puede intentar comprimir el tráfico. Si no aumenta 100 veces, aún obtendrá algún beneficio de rendimiento

+0

Si bien puedo ver que es un beneficio cuando los datos se transfieren a través de una red, en mi caso no solo aumentará la carga de procesamiento? La CPU ya está cerca del 100%. –

+1

@Ian: en este caso, parece que los viajes de ida y vuelta son el problema más probable; comprimir el tráfico ayuda * ancho de banda *, pero no ayuda * latencia *. –

3

¿Podría hacer MyComponent una clase que almacenará en caché los valores y solo los presentará cuando se llame a SaveCustomer()?

+0

Debería haber sido más claro en mi pregunta original: la mayoría de las veces el front-end parece leer del objeto remoto, no escribir en él. Pero sospecho que el objeto remoto puede cambiar en cualquier momento, por lo que el almacenamiento en caché en el front-end puede no ser una opción. –

+0

@IanGoldby: Si no puede reducir los viajes redondos de la red, o el costo de cada viaje de ida y vuelta, entonces está atascado. Tendrá que comprometerse (o usar magia). – Richard

+0

Si el objeto se solicita mucho, aún podría considerar almacenarlo en la memoria caché, aunque solo sea por unos segundos. Realmente depende de la frecuencia con que el cliente solicite los datos y cuán crítico es. ¡Buena suerte! – flayn

1

Si necesita los últimos datos (siempre vea el valor real), y el costo de obtener los datos cada vez domina el tiempo de ejecución, entonces necesita ser radical.

¿Qué le parece cambiar el sondeo para empujar. En lugar de llamar al lado remoto cada vez que necesita un valor, haga que el control remoto presione todos los cambios y guarde en caché los últimos valores localmente.

Las búsquedas locales (después de la obtención inicial) están siempre actualizadas con toda la sobrecarga remota que se realiza en segundo plano (en otra secuencia). Solo tenga cuidado con la seguridad del hilo para tipos no atómicos.

5

En resumen, no, no hay ganancias rápidas aquí. Personalmente quisiera no hacer MyComponent (como un DTO) un MarshalByRefObject (que es probablemente el problema), ya que los viajes redondos van a paralizarlo. Lo mantendría como una clase normal, y solo movería algunos métodos clave para bombearlos (es decir, tener una clase MarshalByRefmanager/repository/etc).

Eso debería reducir ida y vuelta; si todavía tiene problemas, entonces probablemente sea ancho de banda relacionado; esto es más fácil de arreglar; por ejemplo, cambiando el serializador. protobuf-net le permite hacer esto fácilmente implementando ISerializable y reenviando los dos métodos (uno desde la interfaz, más el ctor) al ProtoBuf.Serializer - luego hace todo el trabajo por usted, y trabaja con comunicación remota. Puedo proporcionar ejemplos de esto si lo desea.

En realidad, protobuf-net puede ayudar con el uso de la CPU también, ya que es un serializador mucho más eficiente de la CPU.

Cuestiones relacionadas