2009-08-05 11 views
70

Tutti sembrano dire che le pipe denominate sono più veloci dei socket IPC. Quanto sono più veloci? Preferirei usare le prese perché possono fare comunicazione bidirezionale e sono molto flessibili, ma sceglieranno la velocità rispetto alla flessibilità se è di notevole entità.Prestazioni IPC: named pipe vs socket

+10

Il tuo chilometraggio può variare. :) Uso tipico del profilo per l'applicazione desiderata e scegliere la migliore delle due. Quindi, profili pipe anonimi, socket di altri domini e famiglie, semafori e memoria condivisa o code di messaggi (SysV e POSIX), segnali in tempo reale con una parola di dati o altro. 'pipe (2)' (ehm, 'mkfifo (3)'?) potrebbe essere il vincitore, ma non lo saprai fino a quando non ci proverai. – pilcrow

+2

Code messaggi SysV FTW! Non ho idea se sono veloci, ho solo un debole per loro. –

+2

Che cos'è la "velocità" in questo caso? Velocità di trasferimento dati complessiva? O latenza (quanto velocemente il primo byte arriva al ricevitore)? Se si desidera il trasferimento rapido dei dati locali, è difficile battere la memoria condivisa. Se la latenza è un problema, però, la domanda diventa più interessante ... –

risposta

4

I tubi e le prese nominali non sono funzionalmente equivalenti; i socket forniscono più funzionalità (sono bidirezionali, per cominciare).

Non siamo in grado di dirti quali saranno le prestazioni migliori, ma sospetto fortemente che non abbia importanza.

I socket di dominio Unix faranno più o meno quello che saranno i socket tcp, ma solo sulla macchina locale e con (forse un po ') overhead inferiore.

Se un socket Unix non è abbastanza veloce e si stanno trasferendo molti dati, si consideri l'utilizzo della memoria condivisa tra client e server (che è molto più complicato da configurare).

Unix e NT hanno entrambi "named pipe" ma sono completamente diversi nel set di funzionalità.

+1

Bene, se apri 2 pipe, otterrai anche un comportamento bidi. – Pacerier

46

Suggerirei di prendere prima il percorso facile, isolando attentamente il meccanismo ipc in modo che sia possibile passare da un socket all'altro, ma senza dubbio andrei prima con il socket. Dovresti essere sicuro che le prestazioni IPC sono un problema prima dell'ottimizzazione preventiva.

E se si verifica un problema a causa della velocità IPC, penso che si dovrebbe prendere in considerazione il passaggio alla memoria condivisa piuttosto che andare al pipe.

Se si desidera eseguire alcuni test di velocità di trasferimento, è necessario provare socat, che è un programma molto versatile che consente di creare quasi ogni tipo di tunnel.

+2

+1 per socat, non l'avevo visto prima dello – galaktor

+1

@shodanex, Con "memoria condivisa" intendi thread o ..? – Pacerier

25

Sono d'accordo con shodanex, sembra che tu stia prematuramente cercando di ottimizzare qualcosa che non è ancora problematico. A meno che tu non sappia che lo sa di socket, li userò semplicemente.

Un sacco di persone che giurano per pipe nominate trovano un piccolo risparmio (a seconda di quanto bene tutto il resto è scritto), ma finiscono con il codice che impiega più tempo a bloccare una risposta IPC che a fare un lavoro utile. Certo, gli schemi non bloccanti aiutano questo, ma quelli possono essere complicati. Trascorrere anni a portare il vecchio codice nell'età moderna, posso dire, l'accelerazione è quasi nulla nella maggior parte dei casi che ho visto.

Se pensi davvero che i socket ti rallentino, allora vai fuori dal gate usando la memoria condivisa prestando attenzione a come usi i lucchetti. Di nuovo, in tutta l'attualità, potresti trovare una piccola accelerazione, ma nota che stai sprecando una parte di essa in attesa di blocchi di esclusione reciproca. Non ho intenzione di sostenere un viaggio a futex hell (beh, non piuttosto inferno più nel 2015, a seconda della vostra esperienza).

Pound per libbra, i socket sono (quasi) sempre il modo migliore per passare allo spazio utente IPC con un kernel monolitico .. e (di solito) il più semplice da eseguire il debug e il mantenimento.

6

Se non hai bisogno di velocità, le prese sono la via più facile da percorrere!

Se quello che stai guardando è la velocità, la soluzione più veloce è la memoria condivisa, non le named pipe.

7

Per la comunicazione a due vie con named pipe:

  • Se si dispone di alcuni processi, è possibile aprire due tubi per due direzioni (processA2ProcessB e processB2ProcessA)
  • Se si dispone di molti processi, è possibile aprire in e fuori tubi per ogni processo (processAin, processAout, processBin, processBout, processCin, processCout ecc)
  • Oppure si può andare ibrido come sempre :)

Nam le pipe ed sono abbastanza facili da implementare.

E.g. Ho implementato un progetto in C con named pipe, grazie alla comunicazione standard basata su input-output di file (fopen, fprintf, fscanf ...) è stato così facile e pulito (se anche questa è una considerazione).

ho addirittura codificato con java (ero serializzazione e l'invio di oggetti su di loro!)

named pipe ha uno svantaggio:

  • che non sono scalabili su più computer, come le prese in quanto si basano su filesystem (supponendo che il filesystem condiviso non sia un'opzione)
20

Ricordare che socket non significa necessariamente IP (e TCP o UDP). È inoltre possibile utilizzare i socket UNIX (PF_UNIX), che offrono un notevole miglioramento delle prestazioni rispetto alla connessione a 127.0.0.1

+1

Che dire di Windows? – Pacerier

+1

@Pacerier Purtroppo, non è possibile creare socket locali su Windows allo stesso modo dello spazio dei nomi astratto su UNIX. Ho trovato socket PF_UNIX per essere sostanzialmente più veloce (> 10%) rispetto alla maggior parte degli altri metodi descritti in questa pagina. – EntangledLoops

4

Un problema con i socket è che non hanno un modo per svuotare il buffer. Esiste qualcosa chiamato algoritmo Nagle che raccoglie tutti i dati e li scarica dopo 40 ms. Quindi se è la reattività e non la larghezza di banda, potresti stare meglio con una pipa.

È possibile disattivare Nagle con l'opzione socket TCP_NODELAY, ma la lettura non riceverà mai due messaggi brevi in ​​una singola chiamata di lettura.

Quindi testarlo, ho finito con niente di tutto questo e ho implementato le code basate sulla memoria mappata con pthread mutex e semaforo nella memoria condivisa, evitando molte chiamate al sistema del kernel (ma oggi non sono più molto lente).

+1

"Quindi testalo" <- parole per vivere. – Koshinae

1

È possibile utilizzare una soluzione leggera come ZeroMQ [zmq/0mq]. È molto facile da usare e molto più veloce delle prese.

+1

Potrebbe piacere, indovinare Amit, la prossima opera di Martin SUSTRIK - conforme a POSIX ** 'nanomsg' **. Ad ogni modo, benvenuto e divertiti in questo fantastico posto e diventa membro attivo. – user3666197

+0

Ci proveremo di sicuro, grazie. –