Bei einer sehr kleinen Anzahl von Sockets (hängt natürlich von Ihrer Hardware ab, aber es handelt sich um etwas in der Größenordnung von 10 oder weniger) kann select die Speicherauslastung und die Laufzeitgeschwindigkeit übertreffen. Natürlich sind bei so wenigen Steckdosen beide Mechanismen so schnell, dass Sie sich in den allermeisten Fällen nicht wirklich um diesen Unterschied kümmern.
Eine Klarstellung. Sowohl Select als auch Epoll skalieren linear. Ein großer Unterschied besteht jedoch darin, dass die APIs mit Blick auf den Benutzerbereich Komplexitäten aufweisen, die auf unterschiedlichen Faktoren beruhen. Die Kosten eines select
Anrufs hängen ungefähr vom Wert des Dateideskriptors mit der höchsten Nummer ab, den Sie übergeben. Wenn Sie auf einem einzelnen fd 100 auswählen, ist das ungefähr doppelt so teuer wie auf einem einzelnen fd 50. Das Hinzufügen von mehr fds unter dem höchsten ist nicht ganz kostenlos, daher ist es in der Praxis etwas komplizierter, aber dies ist eine gute erste Annäherung für die meisten Implementierungen.
Die Kosten für epoll liegen näher an der Anzahl der Dateideskriptoren, auf denen tatsächlich Ereignisse vorhanden sind. Wenn Sie 200 Dateideskriptoren überwachen, aber nur 100 von ihnen Ereignisse enthalten, zahlen Sie (sehr grob) nur für diese 100 aktiven Dateideskriptoren. Hier bietet epoll tendenziell einen seiner Hauptvorteile gegenüber ausgewählten. Wenn Sie tausend Kunden haben, die größtenteils untätig sind, zahlen Sie bei Verwendung von select immer noch für alle tausend. Mit epoll haben Sie jedoch nur wenige - Sie zahlen nur für diejenigen, die zu einem bestimmten Zeitpunkt aktiv sind.
All dies bedeutet, dass epoll bei den meisten Workloads zu einer geringeren CPU-Auslastung führt. Was die Speichernutzung angeht, ist es ein bisschen schwierig. select
schafft es, alle notwendigen Informationen auf sehr kompakte Weise darzustellen (ein Bit pro Dateideskriptor). Und die FD_SETSIZE-Beschränkung (normalerweise 1024) für die Anzahl der Dateideskriptoren, mit denen Sie arbeiten können, select
bedeutet, dass Sie nie mehr als 128 Byte für jeden der drei fd-Sätze ausgeben, mit denen Sie arbeiten könnenselect
(Lesen, Schreiben, Ausnahme). Im Vergleich zu diesen maximal 384 Bytes ist Epoll eine Art Schwein. Jeder Dateideskriptor wird durch eine Multi-Byte-Struktur dargestellt. In absoluten Zahlen wird jedoch immer noch nicht viel Speicher benötigt. Sie können eine große Anzahl von Dateideskriptoren in ein paar Dutzend Kilobyte darstellen (ungefähr 20.000 pro 1000 Dateideskriptoren, glaube ich). Sie können auch die Tatsache select
berücksichtigen , dass Sie alle 384 dieser Bytes ausgeben müssen, wenn Sie nur einen Dateideskriptor überwachen möchten, dessen Wert jedoch 1024 beträgt, während Sie mit epoll nur 20 Bytes ausgeben würden. Trotzdem sind alle diese Zahlen ziemlich klein, so dass es keinen großen Unterschied macht.
Und es gibt noch den anderen Vorteil von epoll, den Sie vielleicht bereits kennen, dass er nicht auf FD_SETSIZE-Dateideskriptoren beschränkt ist. Sie können damit so viele Dateideskriptoren überwachen, wie Sie haben. Und wenn Sie nur einen Dateideskriptor haben, dessen Wert jedoch größer als FD_SETSIZE ist, funktioniert epoll auch damit, aber select
nicht.
Zufällig habe ich kürzlich auch einen kleinen Nachteil epoll
gegenüber select
oder entdeckt poll
. Während keine dieser drei APIs normale Dateien (dh Dateien in einem Dateisystem) unterstützt select
und poll
diese mangelnde Unterstützung als Bericht über solche Deskriptoren darstellt, die immer lesbar und immer beschreibbar sind. Dies macht sie für jede sinnvolle Art von nicht blockierenden Dateisystem-E / A ungeeignet. Ein Programm, das einen Dateideskriptor aus dem Dateisystem verwendet select
oder poll
zufällig findet, funktioniert zumindest weiterhin (oder wenn dies fehlschlägt, liegt dies nicht daran von select
oder poll
), wenn auch vielleicht nicht mit der besten Leistung.
Auf der anderen Seite epoll
wird schnell mit einem Fehler ( EPERM
anscheinend) fehlschlagen , wenn Sie aufgefordert werden, einen solchen Dateideskriptor zu überwachen. Genau genommen ist das kaum falsch. Es signalisiert lediglich explizit den Mangel an Unterstützung. Normalerweise würde ich explizite Fehlerbedingungen begrüßen, aber diese sind nicht dokumentiert (soweit ich das beurteilen kann) und führen zu einer vollständig fehlerhaften Anwendung und nicht zu einer Anwendung, die lediglich mit potenziell verschlechterter Leistung arbeitet.
In der Praxis ist der einzige Ort, an dem ich dies gesehen habe, die Interaktion mit stdio. Ein Benutzer kann stdin oder stdout von / in eine normale Datei umleiten. Während früher stdin und stdout eine Pipe gewesen wären - von epoll ganz gut unterstützt -, wird es dann zu einer normalen Datei und epoll schlägt laut fehl und bricht die Anwendung.
poll
Vollständigkeit halber explizit zu beschreiben ?