Pour un très petit nombre de sockets (cela 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 en termes d'utilisation de la mémoire et de 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.
Une clarification, cependant. Les deux select et epoll sont mis à l'échelle de manière linéaire. Une grande différence, cependant, est que les API orientées vers l'espace utilisateur présentent des complexités basées sur des choses différentes. Le coût d'un select
appel correspond à peu près à la valeur du descripteur de fichier numéroté le plus élevé que vous lui transmettez. Si vous sélectionnez sur un seul fd, 100, alors c'est à peu près deux fois plus cher que de sélectionner sur un seul fd, 50. Ajouter plus de fds en dessous du plus élevé n'est pas tout à fait gratuit, donc c'est un peu plus compliqué que cela en pratique, mais cela 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 contiennent réellement des événements. Si vous surveillez 200 descripteurs de fichiers, mais que seuls 100 d'entre eux ont des événements, vous ne payez (très grossièrement) que pour ces 100 descripteurs de fichiers actifs. C'est là qu'epoll a tendance à offrir l'un de ses principaux avantages par rapport à select. Si vous avez un millier de clients pour la plupart inactifs, lorsque vous utilisez select, vous payez toujours pour les mille d'entre eux. Cependant, avec epoll, c'est comme si vous n'en aviez que quelques-uns - vous ne payez que pour ceux qui sont actifs à un moment donné.
Tout cela signifie qu'epoll réduira l'utilisation du processeur pour la plupart des charges de travail. En ce qui concerne l'utilisation de la mémoire, c'est un peu compliqué. select
parvient à représenter toutes les informations nécessaires de manière très compacte (un bit par descripteur de fichier). Et la limitation FD_SETSIZE (généralement 1024) sur le nombre de descripteurs de fichiers que vous pouvez utiliser select
signifie que vous ne dépenserez jamais plus de 128 octets pour chacun des trois ensembles de fd que vous pouvez utiliser avecselect
(lecture, écriture, exception). Comparé à ces 384 octets maximum, epoll est une sorte de porc. Chaque descripteur de fichier est représenté par une structure multi-octets. Cependant, en termes absolus, cela n'utilisera toujours pas beaucoup de mémoire. Vous pouvez représenter un grand nombre de descripteurs de fichiers dans quelques dizaines de kilo-octets (environ 20k pour 1000 descripteurs de fichiers, je pense). Et vous pouvez également ajouter le fait que vous devez dépenser les 384 octets avec select
si vous ne voulez surveiller qu'un seul descripteur de fichier mais que sa valeur se trouve être de 1024, alors qu'avec epoll vous ne dépenseriez que 20 octets. Pourtant, tous ces chiffres sont assez petits, donc cela ne fait pas beaucoup de différence.
Et il y a aussi cet autre avantage d'epoll, dont vous êtes peut-être déjà conscient, qu'il n'est pas limité aux descripteurs de fichier FD_SETSIZE. Vous pouvez l'utiliser pour surveiller autant de descripteurs de fichiers que vous en avez. Et si vous n'avez qu'un seul descripteur de fichier, mais que sa valeur est supérieure à FD_SETSIZE, epoll fonctionne également avec cela, mais select
pas.
Au hasard, j'ai également découvert récemment un léger inconvénient epoll
par rapport à select
ou poll
. Bien qu'aucune de ces trois API ne prenne en charge les fichiers normaux (c'est-à-dire les fichiers sur un système de fichiers), select
et poll
présente ce manque de support comme rapportant de tels descripteurs comme toujours lisibles et toujours inscriptibles. Cela les rend inadaptés à tout type significatif d'E / S de système de fichiers non bloquant, un programme qui utilise select
ou poll
et rencontre un descripteur de fichier du système de fichiers continuera au moins à fonctionner (ou s'il échoue, ce ne sera pas parce que de select
ou poll
), mais il peut - être pas la meilleure performance.
D'autre part, epoll
échouera rapidement avec une erreur ( EPERM
, apparemment) lorsqu'on lui demande de surveiller un tel descripteur de fichier. À proprement parler, ce n'est guère incorrect. Cela signale simplement son manque de soutien de manière explicite. Normalement, j'applaudirais les conditions d'échec explicites, mais celle-ci est non documentée (pour autant que je sache) et entraîne une application complètement cassée, plutôt qu'une application qui fonctionne simplement avec des performances potentiellement dégradées.
En pratique, le seul endroit où j'ai vu cela se produire est lors de l'interaction avec stdio. Un utilisateur peut rediriger stdin ou stdout depuis / vers un fichier normal. Alors que précédemment stdin et stdout auraient été un tube - supporté par epoll très bien - il devient alors un fichier normal et epoll échoue bruyamment, cassant l'application.
poll
pour être complet?