2010-03-25 16 views
10

Tutto ciò che ho letto sui socket in .NET dice che il pattern asincrono offre prestazioni migliori (specialmente con il nuovo SocketAsyncEventArgs che salva sull'assegnazione).Sincronizzazione vs. Prestazioni dei socket asincroni in .NET

Penso che questo abbia senso se stiamo parlando di un server con molte connessioni client dove non è possibile allocare un thread per connessione. Quindi posso vedere il vantaggio di utilizzare i thread ThreadPool e ottenere richiami asincroni su di essi.

Ma nella mia app, sono il cliente e ho solo bisogno di ascoltare un server che invia dati di tick di mercato su una connessione TCP. Al momento, creo un singolo thread, imposta la priorità su Highest e chiama Socket.Receive() con esso. Il mio thread si blocca su questa chiamata e si riattiva non appena arrivano nuovi dati.

Se dovessi cambiare l'accaduto a un modello asincrono in modo che ho un callback quando c'è nuovi dati, vedo due questioni

  1. I fili ThreadPool avrà priorità predefinita in modo da sembra che saranno strettamente peggio del mio thread che ha la priorità più alta.

  2. A un certo punto dovrò ancora inviare tutto tramite un singolo thread. Dite che ottengo N callback quasi alla stessa ora su N thread threadpool diversi che mi informano che ci sono nuovi dati. Gli array di byte N che recapitano non possono essere elaborati sui thread del threadpool perché non è garantito che rappresentino N messaggi di dati di mercato univoci perché TCP è basato su flusso. Dovrò bloccare e mettere i byte in un array in ogni caso e segnalare qualche altro thread in grado di elaborare ciò che è nella matrice. Quindi non sono sicuro di cosa abbia N thread threadpool mi sta comprando.

Sto pensando a questo sbagliato? C'è un motivo per usare il patter Async nel mio caso specifico di un client connesso ad un server?

UPDATE:

Quindi penso che ero mis-comprensione del modello asincrono a (2) di cui sopra. Avrei ricevuto una richiamata su un thread di lavoro quando c'erano dati disponibili. Quindi inizierei un'altra ricezione asincrona e ricevo un'altra richiamata, ecc. Non vorrei ricevere N callback allo stesso tempo.

La domanda è ancora la stessa. C'è qualche ragione per cui i callback sarebbero migliori nella mia specifica situazione in cui sono il client e sono connesso solo a un server.

risposta

5

La parte più lenta dell'applicazione sarà la comunicazione di rete. È molto probabile che non cambierai praticamente le prestazioni per un thread, un client di connessione modificando le cose come questa. La stessa comunicazione di rete minimizzerà tutti gli altri contributi all'elaborazione o al tempo di commutazione del contesto.

dire che ricevo N callback quasi stesso tempo su N fili diversa ThreadPool mi notifica che c'è nuovi dati.

Perché succederà? Se si dispone di un socket, si esegue l'operazione Begin per ricevere dati e si ottiene esattamente una richiamata al termine. Quindi decidi se fare un'altra operazione. Sembra che tu lo stia complicando eccessivamente, anche se forse lo sto semplificando eccessivamente riguardo a ciò che stai cercando di fare.

In sintesi, direi: scegli il modello di programmazione più semplice che ti fa ottenere ciò che desideri; considerando le scelte disponibili nel tuo scenario, è improbabile che possano fare una differenza notevole per le prestazioni indipendentemente da dove tu vada. Con il modello di blocco, stai "sprecando" una discussione che potrebbe fare del vero lavoro, ma hey ... forse non hai un vero lavoro da fare.

+0

Grazie per la risposta. Hai ragione, stavo guardando questo esempio sbagliato. Quindi inizio e ricevo una richiamata su qualche thread del threadpool quando ci sono dati. Quindi lo elaboro e posso quindi decidere che voglio continuare ad ascoltare di più e ottenere un altro callback. Ma anche se questo è il caso, non vedo come questo potrebbe essere più veloce di avere solo un thread ad alta priorità dedicato a fare il Receive(). –

+0

Prima di tutto, eviterei di impostare la priorità dei thread. Sono abbastanza sicuro che generalmente non è raccomandato. È meglio lasciare che tutti i thread che hanno lavoro abbiano accesso uguale alla CPU. In secondo luogo, il mio punto è che * non * sarà più veloce. Il valore delle API asincrone è che ti permettono di evitare di legare un thread (una risorsa costosa a causa delle dimensioni di uno stack di chiamate) in pura attesa, e se hai solo una connessione e un thread e niente da fare fino a quando non ottenere indietro i dati, quindi non c'è davvero nessun costo elevato nel legare un thread. L'eccezione è se si utilizza Silverlight, in quanto ha solo asincrono. –

+0

"Più veloce" è quasi completamente discutibile in questo scenario, perché questi tipi di scelte andranno persi nel rumore rispetto al costo della comunicazione di rete stessa.Non c'è letteralmente nulla da guadagnare nelle prestazioni passando da queste tecniche. –

3

La regola numero uno di prestazioni è solo cercare di migliorare quando è necessario.

Vedo che parli degli standard ma non cito mai dei problemi, se non ne hai nessuno, allora non devi preoccuparti di quello che dicono gli standard.

+0

È vero, non ci sono problemi ora. Ma è difficile da misurare. Potrei configurare due versioni dell'app, una con il modello asincrono e una con il modello di sincronizzazione e misurarla. Ma sarebbe bello sapere se qualcun altro ha già fatto questo e può dirmi che async sarà più veloce e perché. –

2

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

quanto ho capito, sei un cliente qui, avendo solo una singola connessione.
I dati su questa connessione arriva in ordine, consumato da un unico filo.

Probabilmente perderai le prestazioni se invece lo riceverai piccole somme su thread separati, solo per poterle assemblare in un secondo momento in modo serializzato - e quindi come single-threaded -.
Molto rumore per nulla.


Non hai davvero bisogno di accelerare, probabilmente non puoi.

Che cosa si può fare, tuttavia è di inviare unità di lavoro ad altri thread dopo che li ricevete. Per questo non è necessario SocketAsyncEventArgs. Questo potrebbe aumentare la velocità di.

Come sempre, misurare la misura &.
Inoltre, solo perché è possibile, ciò non significa che dovresti.
Se le prestazioni sono sufficienti per il prossimo futuro, perché complicare le cose?

+0

Sono d'accordo. Anche quello era il mio pensiero. Se potessi ottenere più callback su più thread ThreadPool, sembra una cattiva idea. Ma ero scettico perché ogni articolo su socket perf che ho letto per i socket .NET dice quanto sono grandi i socket asincroni (e sono sicuro che sono molto meglio per molte applicazioni). Volevo solo assicurarmi che non mi mancasse qualcosa per il mio caso particolare. –