2010-03-25 10 views
10

Todo lo que he leído sobre sockets en .NET dice que el patrón asíncrono ofrece un mejor rendimiento (especialmente con el nuevo SocketAsyncEventArgs que ahorra en la asignación).Sincronización vs. Async Sockets Performance en .NET

Creo que esto tiene sentido si estamos hablando de un servidor con muchas conexiones de clientes donde no es posible asignar un hilo por conexión. Luego puedo ver la ventaja de utilizar los subprocesos de ThreadPool y obtener devoluciones de llamada asíncronas.

Pero en mi aplicación, soy el cliente y solo necesito escuchar a un servidor que envía datos de marcas del mercado a través de una conexión tcp. En este momento, creo un único hilo, establezco la prioridad en Más Alto y llamo a Socket.Receive() con él. Mi hilo bloquea en esta llamada y se despierta una vez que llegan nuevos datos.

Si tuviera que cambiar esto a un patrón asincrónico de modo que consiga una devolución de llamada cuando no hay nuevos datos, veo dos problemas

  1. Los hilos ThreadPool tendrá prioridad por defecto por lo que parece que será estrictamente peor que mi propio hilo, que tiene la más alta prioridad.

  2. Todavía tendré que enviar todo a través de un único hilo en algún momento. Digamos que obtengo N devoluciones de llamada casi al mismo tiempo en N subprocesos de subprocesos diferentes que me notifican que hay nuevos datos. Las matrices de N byte que entregan no se pueden procesar en los subprocesos de subprocesos porque no hay garantía de que representen N mensajes de datos de mercado únicos porque TCP se basa en secuencias. Tendré que bloquear y poner los bytes en una matriz de todos modos y señalar algún otro hilo que pueda procesar lo que hay en la matriz. Así que no estoy seguro de qué es lo que tiene N hilos de rosca me está comprando.

¿Estoy pensando en esto mal? ¿Hay alguna razón para usar el patrón Async en mi caso específico de un cliente conectado a un servidor?

ACTUALIZACIÓN:

Así que creo que era malentendidos en el patrón asincrónico (2) anterior. Me gustaría recibir una devolución de llamada en un hilo de trabajo cuando había datos disponibles. Entonces comenzaría otra recepción asíncrona y recibiría otra devolución de llamada, etc. No obtendría N devoluciones de llamada al mismo tiempo.

La pregunta sigue siendo la misma. ¿Hay alguna razón por la cual las devoluciones de llamada serían mejores en mi situación específica donde soy el cliente y solo estoy conectado a un servidor?

Respuesta

5

La parte más lenta de su aplicación será la comunicación de red. Es muy probable que no haga casi ninguna diferencia en el rendimiento de un cliente de conexión de un hilo, un cliente, ajustando cosas como esta. La comunicación de red en sí misma eclipsará todas las demás contribuciones al procesamiento o al tiempo de conmutación de contexto.

decir que llego N devoluciones de llamada en casi al mismo tiempo en diferentes hilos N ThreadPool que reciba una notificación de que hay nuevos datos.

¿Por qué va a suceder eso? Si tiene un socket, tiene una operación en él para recibir datos, y obtiene exactamente una devolución de llamada cuando termina. Luego decides si hacer otra operación. Parece que lo estás complicando demasiado, aunque tal vez estoy simplificando demasiado con respecto a lo que estás tratando de hacer.

En resumen, diría: elija el modelo de programación más simple que le proporcione lo que desea; Considerando las opciones disponibles en su escenario, es poco probable que hagan una diferencia notable en el desempeño, cualquiera sea el que elija. Con el modelo de bloqueo, estás "desperdiciando" un hilo que podría estar haciendo un trabajo real, pero bueno ... tal vez no tengas ningún trabajo real para hacerlo.

+0

Gracias por su respuesta. Tienes razón, miraba mal este ejemplo. Así que empiezo y recibo una devolución de llamada en algún subproceso de subprocesos cuando hay datos. Entonces lo proceso y puedo decidir que quiero seguir escuchando por más y obtener otra devolución de llamada. Pero incluso si este es el caso, no veo cómo esto podría ser más rápido que solo tener un hilo de alta prioridad dedicado a hacer el Receive(). –

+0

En primer lugar, evitaría establecer la prioridad de los hilos. Estoy bastante seguro de que generalmente no es recomendable. Es mejor dejar que todos los hilos que tienen trabajo que hacer obtengan igual acceso a la CPU. En segundo lugar, mi punto es que * * no * será más rápido. El valor de las API asíncronas es que le permiten evitar bloquear un hilo (un recurso costoso debido al tamaño de una pila de llamadas) en espera pura, y si solo tiene una conexión y un hilo, y nada que hacer hasta que usted recuperar los datos, entonces realmente no hay un gran costo en la vinculación de un hilo. La excepción es si usa Silverlight, ya que solo tiene asincrónico. –

+0

"Más rápido" es casi completamente discutible en este escenario, porque este tipo de opciones se perderán en el ruido en comparación con el costo de la comunicación de la red en sí.Literalmente, no se gana nada en el rendimiento cambiando entre estas técnicas. –

3

La regla de rendimiento número uno es solo intentar mejorarla cuando sea necesario.

Veo que menciona los estándares pero nunca menciona los problemas, si no los tiene, entonces no tiene que preocuparse por lo que dicen las normas.

+0

Es cierto, no hay problema ahora. Pero es difícil de medir. Podría configurar dos versiones de la aplicación, una con el patrón asíncrono y otra con el patrón de sincronización y medirla. Pero sería bueno saber si alguien más ya ha hecho esto y puede decirme que la sincronización será más rápida y por qué. –

2

"This class was specifically designed for network server applications that require high performance. "

Según tengo entendido, usted es un cliente aquí, ya que sólo un sola conexión.
de datos en relación con esto llega el fin, consumida por un solo hilo.

Es probable que pierda rendimiento si en su lugar recibe pequeñas cantidades en hilos separados, solo para que pueda ensamblarlos más tarde de manera serializada y, por lo tanto, como un único hilo.
Mucho ruido y pocas nueces.


Realmente no necesita acelerar esto, probablemente no pueda.

Lo que puede hacer, sin embargo, es para despachar unidades de obra a otros hilos después de que los reciba. No necesita SocketAsyncEventArgs para esto. Este podría acelerar las cosas.

Como siempre, mida & medida.
Además, solo porque puede, no significa que deba hacerlo.
Si el rendimiento es suficiente en el futuro previsible, ¿por qué complicar las cosas?

+0

Estoy de acuerdo. Ese fue mi pensamiento también. Si pudiera obtener múltiples devoluciones de llamada en múltiples hilos ThreadPool, parece una mala idea. Pero era escéptico porque cada artículo sobre socket que he leído para los sockets .NET dice cuán geniales son las tomas asíncronas (y estoy seguro de que son mucho mejores para muchas aplicaciones). Solo quería asegurarme de no perderme nada en mi caso particular. –