Prestazioni IPC: Named Pipe vs Socket


114

Tutti sembrano dire che le pipe con nome sono più veloci dei socket IPC. Quanto sono più veloci? Preferirei usare i socket perché possono fare comunicazioni bidirezionali e sono molto flessibili, ma sceglierò la velocità sulla flessibilità se è di importo considerevole.


10
Il tuo chilometraggio varierà. :) Profilo dell'uso tipico per l'applicazione prevista e scegli il migliore dei due. Quindi profilare pipe anonime, 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 finché non proverai.
pilcrow

2
Code di messaggi SysV FTW! Non ho idea se sono veloci, ho solo un debole per loro.
Tom Anderson,

4
Che cos'è la "velocità" in questo caso? Velocità di trasferimento dati complessiva? O latenza (quanto velocemente il primo byte arriva al ricevitore)? Se desideri un trasferimento dati locale veloce, è difficile battere la memoria condivisa. Se la latenza è un problema, però, la domanda diventa più interessante ...
Ian Ni-Lewis

Risposte:


64

Ti suggerirei di prendere prima il percorso facile, isolando attentamente il meccanismo IPC in modo da poter passare da socket a pipe, ma preferirei sicuramente prima il socket. Dovresti assicurarti che le prestazioni dell'IPC siano un problema prima di eseguire l'ottimizzazione preventiva.

E se ti trovi nei guai a causa della velocità IPC, penso che dovresti considerare il passaggio alla memoria condivisa piuttosto che andare in pipe.

Se vuoi fare qualche test sulla velocità di trasferimento, dovresti provare socat , che è un programma molto versatile che ti permette di creare quasi ogni tipo di tunnel.


48

I migliori risultati che otterrai con la soluzione di memoria condivisa .

I named pipe sono solo il 16% migliori dei socket TCP .

I risultati si ottengono con il benchmarking IPC :

  • Sistema: Linux (Linux ubuntu 4.4.0 x86_64 i7-6700K 4.00GHz)
  • Messaggio: 128 byte
  • Conteggio messaggi: 1000000

Punto di riferimento del tubo:

Message size:       128
Message count:      1000000
Total duration:     27367.454 ms
Average duration:   27.319 us
Minimum duration:   5.888 us
Maximum duration:   15763.712 us
Standard deviation: 26.664 us
Message rate:       36539 msg/s

Benchmark FIFO (named pipe):

Message size:       128
Message count:      1000000
Total duration:     38100.093 ms
Average duration:   38.025 us
Minimum duration:   6.656 us
Maximum duration:   27415.040 us
Standard deviation: 91.614 us
Message rate:       26246 msg/s

Benchmark della coda dei messaggi:

Message size:       128
Message count:      1000000
Total duration:     14723.159 ms
Average duration:   14.675 us
Minimum duration:   3.840 us
Maximum duration:   17437.184 us
Standard deviation: 53.615 us
Message rate:       67920 msg/s

Benchmark memoria condivisa:

Message size:       128
Message count:      1000000
Total duration:     261.650 ms
Average duration:   0.238 us
Minimum duration:   0.000 us
Maximum duration:   10092.032 us
Standard deviation: 22.095 us
Message rate:       3821893 msg/s

Benchmark dei socket TCP:

Message size:       128
Message count:      1000000
Total duration:     44477.257 ms
Average duration:   44.391 us
Minimum duration:   11.520 us
Maximum duration:   15863.296 us
Standard deviation: 44.905 us
Message rate:       22483 msg/s

Benchmark dei socket di dominio Unix:

Message size:       128
Message count:      1000000
Total duration:     24579.846 ms
Average duration:   24.531 us
Minimum duration:   2.560 us
Maximum duration:   15932.928 us
Standard deviation: 37.854 us
Message rate:       40683 msg/s

Benchmark ZeroMQ:

Message size:       128
Message count:      1000000
Total duration:     64872.327 ms
Average duration:   64.808 us
Minimum duration:   23.552 us
Maximum duration:   16443.392 us
Standard deviation: 133.483 us
Message rate:       15414 msg/s

1
Grazie per il benchmarking dettagliato. Intendi "multiprocessing.Queue" con "Message Queue"?
ovunccetin

1
Message Queue è una coda di messaggi XSI di sistema ( man7.org/linux/man-pages/man0/sys_msg.h.0p.html )
chronoxor

34

Sono d'accordo con shodanex, sembra che tu stia cercando prematuramente di ottimizzare qualcosa che non è ancora problematico. A meno che tu sappia socket saranno un collo di bottiglia, li userei.

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

Se pensi davvero che i socket ti rallenteranno, esci dal cancello usando la memoria condivisa con molta attenzione a come usi i lucchetti. Ancora una volta, in tutta la realtà, potresti trovare un piccolo aumento di velocità, ma nota che stai sprecando una parte di esso in attesa di blocchi di mutua esclusione. Non ho intenzione di sostenere un viaggio nell'inferno del futex (beh, non proprio più l'inferno nel 2015, a seconda della tua esperienza).

Libbra per libbra, i socket sono (quasi) sempre il modo migliore per utilizzare lo spazio utente IPC in un kernel monolitico .. e (di solito) il più facile da eseguire il debug e la manutenzione.


2
forse un giorno in un lontano futuro utopico avremo un kernel completamente nuovo, modulare e moderno che offre implicitamente tutte le capacità (interprocesso e altre) che attualmente camminiamo su vetri rotti per realizzare ... ma hey .. si può sognare
Gukki5

27

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


1
E Windows?
Pacerier

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

1
devblogs.microsoft.com/commandline/af_unix-comes-to-windows update, i socket Unix sono ora disponibili in Windows 10.
eri0o


11

Se non hai bisogno di velocità, le prese sono il modo più semplice per andare!

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


8

Per la comunicazione bidirezionale con named pipe:

  • Se hai pochi processi, puoi aprire due pipe per due direzioni (processA2ProcessB e processB2ProcessA)
  • Se hai molti processi, puoi aprire e uscire pipe per ogni processo (processAin, processAout, processBin, processBout, processCin, processCout ecc.)
  • Oppure puoi diventare ibrido come sempre :)

Le pipe con nome sono abbastanza facili da implementare.

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

Li ho persino codificati con java (stavo serializzando e inviando oggetti su di loro!)

Le pipe denominate presentano uno svantaggio:

  • non scalano su più computer come i socket poiché si basano sul filesystem (assumendo che il filesystem condiviso non sia un'opzione)

8

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

Puoi disabilitare il Nagle con l'opzione socket TCP_NODELAY ma poi la fine della lettura non riceverà mai due brevi messaggi in una singola chiamata di lettura.

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


3
"Quindi provalo" <- parole per vivere.
Koshinae

6

Tubi e prese con nome non sono funzionalmente equivalenti; i socket forniscono più funzionalità (sono bidirezionali, tanto per cominciare).

Non possiamo dirti quale funzionerà meglio, ma sospetto fortemente che non abbia importanza.

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

Se un socket Unix non è abbastanza veloce e stai trasferendo molti dati, considera l'utilizzo della memoria condivisa tra il tuo client e il server (che è MOLTO più complicato da configurare).

Sia Unix che NT hanno "pipe con nome" ma sono totalmente differenti nel set di funzionalità.


1
Beh, se apri 2 tubi, ottieni anche un comportamento bidi.
Pacerier

4

Puoi utilizzare una soluzione leggera come ZeroMQ [ zmq / 0mq ]. È molto facile da usare e notevolmente più veloce dei socket.


2
Potrebbe piacerti, indovina Amit, il prossimo artwork di Martin SUSTRIK - conforme a POSIX nanomsg. Ad ogni modo, benvenuto e goditi questo fantastico posto e diventa il suo membro contributore attivo.
user3666197
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.