2012-03-28 2 views
5

Attualmente sto programmando un'applicazione client e mi chiedo se dovrei usare il metodo ReceiveAsync o BeginReceive della classe Socket. Ho usato il secondo finora, tuttavia, ho trovato che sembra sottolineare la CPU un po '. Ecco ciò che il mio ciclo di ricezione appare fondamentalmente come:Prestazioni di 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); 
} 

Ora mi sono chiesto se sto facendo qualcosa di sbagliato qui, dal momento che le altre applicazioni che comunicano difficilmente sottolineano la CPU a tutti. E mi chiedo anche se sarebbe meglio usare SocketAsyncEventArgs e ReceiveAsync.

Così qui sono le mie domande:

Perché il mio ciclo sottolineando la CPU così tanto? Devo usare SocketAsyncEventArgs e ReceiveAsync invece di BeginReceive?

+0

Scommetto che è becuase si sta chiamando tua metho d in un ciclo in cui non vi è alcun blocco in modo che si stia esaurendo uno dei core: utilizzare la classe ManualResetEvent per eseguire il blocco manuale, se necessario – markmnl

+0

"socket_ReceiveFallback" è effettivamente un metodo diverso nell'implementazione dell'utente? – markmnl

risposta

5

Ho eseguito il benchmarking di socket sincrono e asincrono su una connessione loopback localhost. I miei risultati erano che la versione asincrona era circa il 30% più lenta. Questo è stato sorprendente per me considerando che l'IO asincrono è di gran moda ora. Non importa quanti thread ho usato. Potrei usare 128 thread e ancora IO sincrono era più veloce.

Il motivo è, credo, che l'IO asincrono richiede più allocazioni e più transizioni in modalità kernel.

Quindi è possibile passare all'IO sincrono se non si prevedono centinaia di connessioni simultanee.

+0

Mi collego solo a un singolo server. Quindi potrei fondamentalmente usare solo i metodi di ricezione e invio regolari? Se voglio che sia asincrono, potrei creare l'intera classe in un thread diverso che probabilmente non finirà per essere molto più lento. – haiyyu

+1

Definirei sicuramente questa opzione. La mia ipotesi è che la versione sincrona sarà più veloce. E più mantenibile! – usr

+0

Lo farò e posterò i risultati in seguito. Inoltre, intendevo dire "Potrei creare l'intero oggetto (non la classe) in un thread diverso". – haiyyu

1

rispondi a questo dovresti profilare la tua domanda. Quello che mi chiedo è

  • perché non vedo EndReceive
  • perché non si utilizza il buffer ricevuto affatto e
  • perché si alloca nuovo di volta in volta i buffer - questa è l'unica opperation qui che dovrebbe prendere tutte le risorse (CPU/memoria)

Date un'occhiata a questo: http://msdn.microsoft.com/de-de/library/dxkwh6zw.aspx

+0

1) Spiacente, ho dimenticato di aggiungerlo al codice. È lì nel programma. Ho modificato il mio post. 2) Sto pensando di usarlo. Tuttavia, anche senza utilizzarlo, il server sottolinea molto la CPU. 3) Quindi sarebbe più intelligente creare un pool di buffer? Lo farò e testerò se cambia qualcosa! Grazie per l'aiuto. – haiyyu

+0

la mia ipotesi migliore a questo punto è che, dal momento che trasferisci solo piccoli blocchi (1kB) e lo fai senza ritardi, non c'è molto da aspettare che l'hardware faccia il suo lavoro (ancora più vero se lo fai sullo stesso computer) , quindi il sistema è impegnato a creare le tue chiamate asincrone. Ma consiglio davvero di trovare un buon profiler (la maggior parte ha prove) o anche di usare il build in (penso a VS prof o maggiore) per trovare il punto debole – Carsten