web-dev-qa-db-fra.com

IPC performance: tuyau nommé contre socket

Tout le monde semble dire que les pipes nommés sont plus rapides que les sockets IPC. Combien sont-ils plus vite? Je préférerais utiliser des sockets, car ils peuvent établir une communication dans les deux sens et sont très flexibles, mais je choisirai la vitesse plutôt que la flexibilité si elle est très importante.

93
user19745

Je suggérerais que vous preniez d'abord le chemin facile, en isolant soigneusement le mécanisme ipc afin que vous puissiez changer de socket en tuyau, mais je choisirais certainement d'abord socket. Vous devez être sûr que les performances IPC sont un problème avant de procéder à l’optimisation préemptive.

Et si vous rencontrez des problèmes à cause de la vitesse IPC), je pense que vous devriez envisager de passer à la mémoire partagée plutôt que d'aller au canal.

Si vous souhaitez effectuer des tests de vitesse de transfert, vous devriez essayer socat , un programme très polyvalent qui vous permet de créer presque tous les types de tunnels.

56
shodanex

Je suis d'accord avec shodanex, il semblerait que vous essayiez prématurément d'optimiser quelque chose qui ne pose pas encore de problème. À moins que vous sachiez que les sockets soient un goulot d'étranglement, je les utiliserais simplement.

Un grand nombre de personnes qui ne jurent que par les canaux nommés réalisent quelques petites économies (en fonction de la manière dont tout le reste est écrit), mais se retrouvent avec un code qui passe plus de temps à bloquer pour une réponse IPC qu'elle ne le fait) Faire des travaux utiles. Bien sûr, les systèmes non bloquants y contribuent, mais cela peut être délicat. Passer des années à introduire le code ancien dans l’ère moderne, je peux dire, l’accélération est presque nulle dans la majorité des cas que j’ai vus.

Si vous pensez vraiment que les sockets vont vous ralentir, sortez de la porte en utilisant la mémoire partagée en faisant très attention à la façon dont vous utilisez les verrous. Encore une fois, en réalité, vous pourriez trouver une petite accélération, mais notez que vous perdez une partie de celle-ci en attente de verrous d’exclusion mutuels. Je ne vais pas recommander un voyage en enfer futex (enfin, pas plutôt enfer en 2015, en fonction de votre expérience).

Pound pour pound, les sockets sont (presque) toujours le meilleur moyen d’utiliser l’espace utilisateur IPC sous un noyau monolithique .. et (généralement) le plus facile à déboguer et à maintenir.

30
Tim Post

N'oubliez pas que sockets ne signifie pas nécessairement IP (et TCP ou UDP). Vous pouvez également utiliser des sockets UNIX (PF_UNIX), qui offrent une amélioration notable des performances par rapport à la connexion à 127.0.0.1.

26
Yuliy

Comme souvent, les chiffres en disent plus que les sentiments, voici quelques données: Pipe vs Unix Socket Performance (opendmx.net) .

Ce repère indique une différence d’environ 12 à 15% de vitesse plus rapide pour les tuyaux.

26
Hibou57

Vous obtiendrez de meilleurs résultats avec une solution à mémoire partagée .

Les canaux nommés ne sont que 16% meilleurs que les sockets TCP .

Les résultats sont obtenus avec benchmarking IPC :

  • Système: Linux (Linux 4.4.0 x86_64 i7-6700K 4.00GHz)
  • Message: 128 octets
  • Nombre de messages: 1000000

Benchmark du tuyau:

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

Repère FIFO (tubes nommés):

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 de Message Queue:

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 de la mémoire partagée:

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 des sockets 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 des sockets du domaine 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

ZeroMQ benchmark:

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
18
chronoxor

Si vous n'avez pas besoin de vitesse, les prises sont le moyen le plus simple d'y aller!

Si vous recherchez la vitesse, la solution la plus rapide est la mémoire partagée, et non les canaux nommés.

10
Damien

Un problème avec les sockets est qu’ils n’ont pas le moyen de vider la mémoire tampon. Il existe un algorithme appelé Nagle qui collecte toutes les données et les vide après 40 ms. Donc, si c'est de la réactivité et non de la bande passante, mieux vaut utiliser un tuyau.

Vous pouvez désactiver le Nagle avec l’option de socket TCP_NODELAY, mais l’extrémité en lecture ne recevra jamais deux messages courts en un seul appel en lecture.

Alors testez-le, je me suis retrouvé avec rien de tout cela et j'ai implémenté des files d'attente basées sur une mappage de mémoire avec pthread mutex et sémaphore dans la mémoire partagée, en évitant beaucoup d'appels système du noyau (mais aujourd'hui, ils ne sont plus très lents).

8
Lothar

Pour une communication bidirectionnelle avec des canaux nommés:

  • Si vous avez peu de processus, vous pouvez ouvrir deux canaux pour deux directions (processA2ProcessB et processB2ProcessA)
  • Si vous avez plusieurs processus, vous pouvez ouvrir et sortir des canaux pour chaque processus (processAin, processAout, processBin, processBout, processCin, processCout, etc.).
  • Ou vous pouvez aller hybride comme toujours :)

Les pipes nommés sont assez faciles à implémenter.

Par exemple. J'ai implémenté un projet en C avec des tubes nommés, grâce à la communication standart de fichiers entrée/sortie (fopen, fprintf, fscanf ...), il était si simple et propre (si cela est également à prendre en compte).

Je les ai même codés avec Java (je sérialisais et leur envoyais des objets!)

Les tubes nommés présentent un inconvénient:

  • ils ne sont pas adaptés à plusieurs ordinateurs, comme les sockets, car ils reposent sur un système de fichiers (en supposant qu'un système de fichiers partagé ne soit pas une option)
8
daghan

Les tuyaux et les sockets nommés ne sont pas équivalents du point de vue fonctionnel. les sockets offrent plus de fonctionnalités (ils sont bidirectionnels, pour commencer).

Nous ne pouvons pas vous dire lequel donnera de meilleurs résultats, mais je soupçonne fortement que cela n'a pas d'importance.

Les sockets de domaine Unix feront à peu près ce que les sockets TCP vont faire, mais uniquement sur la machine locale et avec (peut-être un peu) une surcharge.

Si un socket Unix n'est pas assez rapide et que vous transférez beaucoup de données, envisagez d'utiliser la mémoire partagée entre votre client et votre serveur (ce qui est BEAUCOUP plus compliqué à configurer).

Unix et NT ont tous les deux des "canaux nommés" mais leur ensemble de fonctionnalités est totalement différent.

6
MarkR

Vous pouvez utiliser une solution légère telle que ZeroMQ [ zmq/0mq ]. Il est très facile à utiliser et considérablement plus rapide que les sockets.

3
Amit Vujic