2012-03-28 36 views
5

Actualmente estoy programando una aplicación de cliente y me pregunto si debería usar el método de clase Socket ReceiveAsync o BeginReceive. He estado utilizando este último hasta ahora, sin embargo, he encontrado que parece estresar bastante a la CPU. Aquí es lo que mi recibir bucle se ve básicamente como:Rendimiento de ReceiveAsync vs. BeginReceive

private void socket_ReceiveCallback(IAsyncResult result_) 
{ 
    // does nothing else at the moment 
    socket.EndReceive(result_); 
    byte[] buffer = (byte[])result_.AsyncState; 

    // receive new packet 
    byte[] newBuffer = new byte[1024]; 
    socket.BeginReceive(newBuffer, 0, newBuffer.Length, SocketFlags.None, 
         socket_ReceiveFallback, newBuffer); 
} 

Ahora me he estado preguntando si estoy haciendo algo mal aquí, ya que otras aplicaciones que se comunican casi no hacen hincapié en la CPU en absoluto. Y también me pregunto si estaría mejor con el uso de SocketAsyncEventArgs y ReceiveAsync.

Así que aquí están mis preguntas:

¿Por qué mi bucle Destacando la CPU tanto? ¿Debo usar SocketAsyncEventArgs y ReceiveAsync en lugar de BeginReceive?

+0

i apuesta es becuase que está llamando a su metho d en un bucle donde no hay bloqueo, por lo que está maximizando uno de sus núcleos: use la clase ManualResetEvent para hacer el bloqueo manual si es necesario – markmnl

+0

¿Es realmente "socket_ReceiveFallback" un método diferente en su implementación? – markmnl

Respuesta

5

He estado evaluando las conexiones síncronas y asincrónicas en una conexión de bucle localhost. Mis resultados fueron que la versión asíncrona fue aproximadamente un 30% más lenta. Eso fue sorprendente para mí teniendo en cuenta que Async IO está de moda ahora. No importa cuántos hilos usé. Podría usar 128 hilos y aún IO sincrónico fue más rápido.

La razón de esto es, creo, que async IO requiere más asignaciones y más transiciones de modo kernel.

Así que podría simplemente cambiar a IO sincrónico, si no espera cientos de conexiones simultáneas.

+0

Solo me estoy conectando a un solo servidor. Entonces, básicamente, ¿podría simplemente utilizar los métodos habituales de recepción y envío? Si quiero que sea asincrónico, podría crear toda la clase en un hilo diferente que probablemente no termine siendo mucho más lento. – haiyyu

+1

Definitivamente compararía esta opción. Creo que la versión síncrona será más rápida. ¡Y más sostenible! – usr

+0

Lo haré y publicaré los resultados después. Además, quise decir "Podría crear el objeto completo (no la clase) en un hilo diferente". – haiyyu

1

responda esto tendrías que perfilar tu aplicación. Lo que me pregunto es

  • por qué no veo EndReceive
  • por qué no se utiliza el búfer recibido en absoluto y
  • por qué asignar nuevos y otra vez buffers - esta es la única opperation aquí que debe tener todos los recursos (CPU/memoria)

tener un vistazo a esto: http://msdn.microsoft.com/de-de/library/dxkwh6zw.aspx

+0

1) Lo siento, olvidé agregar eso al código. Está ahí en el programa. He editado mi publicación. 2) Estoy planeando usarlo. Sin embargo, incluso sin usarlo, el servidor acentúa mucho la CPU. 3) Entonces, ¿sería más inteligente crear un grupo de búferes? Haré eso y probaré si cambia algo. Gracias por tu ayuda. – haiyyu

+0

mi mejor conjetura en este punto es que como transfiere solo bloques pequeños (1kB) y lo hace sin demora, no hay mucha espera para que el hardware haga su trabajo (aún más cierto si lo hace en la misma máquina) , por lo que el sistema está ocupado creando sus llamadas asíncronas. Pero realmente recomiendo encontrar un buen generador de perfiles (la mayoría tiene pruebas) o incluso usar la compilación (creo que VS prof o superior) para encontrar el punto débil – Carsten