Mises en garde concernant les réacteurs select/poll vs. epoll dans les réacteurs Twisted

Tout ce que j'ai lu et expérimenté ( applications basées sur la tornade ) me porte à croire qu'ePoll est un remplacement naturel pour les réseaux Select et Poll, en particulier avec Twisted. Ce qui me rend paranoïaque, c'est assez rare pour une meilleure technique ou méthodologie de ne pas avoir de prix.

la lecture d'une vingtaine de comparaisons entre epoll et alternatives montre qu'epoll est clairement le champion de la vitesse et de l'évolutivité, en particulier qu'il s'échelonne dans un mode linéaire qui est fantastique. Cela dit, qu'en est-il de l'utilisation du processeur et de la mémoire, epoll est-il toujours le champion?

88
demandé sur David 2010-01-09 09:39:03

2 réponses

pour un très petit nombre de sockets (varie en fonction de votre matériel, bien sûr, mais nous parlons de quelque chose de l'ordre de 10 ou moins), select peut battre epoll dans l'utilisation de la mémoire et la vitesse d'exécution. Bien sûr, pour un si petit nombre de sockets, les deux mécanismes sont si rapides que vous ne vous souciez pas vraiment de cette différence dans la grande majorité des cas.

un éclaircissement, cependant. L'échelle select et l'échelle epoll sont linéaires. Une grande différence, cependant, est que les IPA confrontés à l'espaceutilisateur ont des complexités qui sont basées sur des choses différentes. Le coût d'un appel select va grossièrement avec la valeur du descripteur de fichier numéroté le plus élevé que vous lui passez. Si vous sélectionnez sur un fd simple, 100, puis c'est à peu près deux fois plus cher que la sélection sur un FD simple, 50. Ajouter plus de fds sous le plus haut n'est pas tout à fait gratuit, donc c'est un peu plus compliqué que cela dans la pratique, mais c'est une bonne première approximation pour la plupart des implémentations.

le coût d'epoll est plus proche du nombre de descripteurs de fichiers qui comportent effectivement des événements. Si vous surveillez 200 descripteurs de fichiers, mais que seulement 100 d'entre eux comportent des événements, alors vous ne payez (en gros) que pour ces 100 descripteurs de fichiers actifs. C'est là qu'epoll tend à offrir l'un de ses principaux avantages par rapport à select. Si vous avez un millier de clients qui sont la plupart du temps inactifs, puis lorsque vous utilisez select vous payez toujours pour tous les mille d'entre eux. Cependant, avec epoll, c'est comme si vous n'en aviez que quelques - uns-vous ne payez que ceux qui sont actifs à un moment donné.

cela signifie qu'epoll réduira l'utilisation de CPU pour la plupart des charges de travail. Aussi loin que l'utilisation de la mémoire va, c'est un peu un tirage au sort. select réussit à représenter toutes les informations nécessaires d'une manière très compacte (un bit par descripteur de fichier). Et la limitation FD_SETSIZE (typiquement 1024) sur le nombre de descripteurs de fichiers que vous pouvez utiliser avec select signifie que vous ne dépenserez jamais plus de 128 octets pour chacun des trois ensembles fd que vous pouvez utiliser avec select (lire, écrire, exception). Comparé à ces 384 octets max, epoll est une sorte de cochon. Chaque descripteur de fichier est représenté par une structure à plusieurs octets. Cependant, en termes absolus, il ne va toujours pas utiliser beaucoup de mémoire. Vous pouvez représenter un grand nombre de descripteurs de fichiers en quelques dizaines de kilooctets (environ 20k par 1000 descripteurs de fichiers, je pense). Et vous pouvez également jeter dans le fait que vous devez passer les 384 octets avec select si vous voulez seulement surveiller un descripteur de fichier mais sa valeur se trouve être 1024, alors qu'avec epoll vous ne passeriez que 20 octets. Pourtant, tous ces chiffres sont assez petits, donc ça ne fait pas beaucoup de différence.

et il y a aussi cet autre avantage d'epoll, dont vous êtes peut-être déjà au courant, qu'il n'est pas limité aux descripteurs de fichiers FD_SETSIZE. Vous pouvez l'utiliser pour surveiller autant de descripteurs de fichiers que vous avoir. Et si vous n'avez qu'un seul descripteur de fichier, mais que sa valeur est supérieure à FD_SETSIZE, epoll fonctionne avec cela aussi, mais select ne fonctionne pas.

au hasard, j'ai aussi récemment découvert un léger inconvénient à epoll par rapport à select ou poll . Bien qu'aucune de ces trois API ne supporte les fichiers normaux (c'est-à-dire les fichiers sur un système de fichiers), select et poll présentent ce manque de support comme le fait de rapporter de tels descripteurs comme toujours lisibles et toujours accessible en écriture. Cela les rend inappropriés pour tout type significatif de non-blocage du système de fichiers I/O, UN programme qui utilise select ou poll et qui rencontre un descripteur de fichier du système de fichiers va au moins continuer à fonctionner (ou s'il échoue, ce ne sera pas à cause de select ou poll ), bien que ce ne soit peut-être pas avec la meilleure performance.

d'autre part, epoll échouera rapidement avec une erreur ( EPERM , apparemment) quand demandé de surveiller un tel descripteur de fichier. Strictement parlant, ce n'est pas incorrect. C'est simplement signe de son manque de soutien d'une manière explicite. Normalement, j'applaudirais les conditions de défaillance explicites, mais celle-ci n'est pas documentée (pour autant que je puisse dire) et aboutit à une application complètement cassée, plutôt qu'une qui fonctionne simplement avec des performances potentiellement dégradées.

dans la pratique, le seul endroit où je l'ai vu est en interaction avec stdio. Un l'utilisateur peut rediriger stdin ou stdout depuis/vers un fichier normal. Alors qu'auparavant stdin et stdout auraient été un tuyau-supporté par epoll tout juste parfait-il devient alors un fichier normal et epoll échoue bruyamment, brisant l'application.

182
répondu Jean-Paul Calderone 2010-05-19 02:43:52

dans les tests de mon entreprise, un problème avec epoll() est apparu, donc un seul coût par rapport à select.

lorsqu'on essaie de lire à partir du réseau avec un timeout, créer un epoll_fd ( au lieu d'un fd_set ), et ajouter le fd à l'epoll_fd, est beaucoup plus coûteux que de créer un fd_set (qui est un simple malloc).

selon la réponse précédente, comme le nombre de FDs dans le processus devient important, le coût de select() devient plus élevé, mais en nos tests, même avec des valeurs de fd dans les 10.000, select était toujours un gagnant. Il s'agit de cas où il n'y a qu'un fd qu'un thread attend, et qui essaient simplement de surmonter le fait que network read, et network write, n'ont pas de temps mort lorsqu'ils utilisent un modèle de thread bloqué. Bien sûr, les modèles de filetage de blocage sont de faibles performances par rapport aux systèmes de réacteur non-bloquants, mais il y a des occasions où, pour s'intégrer à une base de code particulière, il est nécessaire.

Ce type de cas d'utilisation est rare dans les applications haute performance, car un modèle de réacteur n'a pas besoin de créer un nouveau epoll_fd à chaque fois. Pour le modèle où un epoll_fd est de longue durée- - - ce qui est clairement préférable pour toute conception de serveur de haute performance - - - epoll est le gagnant évident dans tous les sens.

3
répondu Brian Bulkowski 2014-04-30 07:33:05