2010-05-06 10 views
5

Ich entwerfe Ereignisschleife für asynchrone Socket IO mit Epoll/devpoll/kqueue/poll/auswählen (einschließlich Windows-Select).Asynchrone Ereignisschleife Design und Probleme

Ich habe zwei Möglichkeiten der Durchführung, IO-Betrieb:

Non-Blocking-Modus Umfrage auf EAGAIN

  1. Set Socket nicht blockierenden Modus.
  2. Lesen/Schreiben an Buchse.
  3. Wenn der Vorgang erfolgreich ist, nach der Beendigungsbenachrichtigung an die Ereignisschleife.
  4. Wenn ich EAGAIN bekomme, füge Socket zu "select list" hinzu und suche den Socket ab.

Polling-Modus: Umfrage und dann

  1. socket ausführen Liste auswählen und abrufen.
  2. Warten auf Benachrichtigung, dass es lesbar beschreibbar ist
  3. Lese-/
  4. Beitrag Abschlussmeldung an Eventloop von sucseeds schreiben

Für mich ist es wie bei der ersten weniger System würde erfordern, sieht aufruft, wenn im normalen Modus , speziell für das Schreiben in Socket (Puffer sind ziemlich groß). Auch sieht es so aus, dass es möglich wäre, den Overhead über die Anzahl von "Select" Ausführungen zu reduzieren, besonders ist es nett, wenn Sie nicht etwas haben, das als epoll/devpoll/kqueue gut skaliert.

Fragen:

  • Gibt es irgendwelche Vorteile des zweiten Ansatzes?
  • Gibt es Portabilitätsprobleme mit nicht blockierenden Operationen auf Sockets/Dateideskriptoren über zahlreiche Betriebssysteme: Linux, FreeBSD, Solaris, MacOSX, Windows.

Hinweise: Bitte schlagen nicht Event-Loop/socket-api Implementierungen

Antwort

3

Ich bin nicht sicher, ob es irgendeine plattformübergreifende Problem mit vorhandenen; Sie müssten höchstens Windows Sockets API verwenden, aber mit den gleichen Ergebnissen.

Ansonsten scheinen Sie in beiden Fällen abgefragt zu haben (Vermeidung blockierender Wartezeiten), daher sind beide Ansätze in Ordnung. Solange Sie sich nicht in die Lage versetzen zu blockieren (zB lesen, wenn keine Daten vorhanden sind, schreiben Sie, wenn der Puffer voll ist), macht das überhaupt keinen Unterschied.

Vielleicht ist der erste Ansatz einfacher zu verstehen; Also, geh damit.

Es könnte für Sie interessant sein, die Dokumentation von libev und die c10k problem für interessante Ideen/Ansätze zu diesem Thema zu überprüfen.

2

Der erste Entwurf ist die Proactor Pattern, die zweite der Reactor Pattern

Ein Vorteil des Reactor ist, dass Sie Ihre API entwerfen können, so dass Sie keine Lesepuffer zuweisen müssen, bis die Daten tatsächlich gibt es gelesen werden. Dies verringert die Speicherauslastung, während Sie auf E/A warten.

+0

Ich sehe keinen Grund, warum Sie nicht warten können, Speicher un zuweisen bis benötigt mit dem ersten Ansatz. Fehle ich etwas? – Ioan

+2

Ich nehme an, aber in der Praxis ist es nicht so implementiert. Im ersten Fall benötigen Sie den verfügbaren Puffer aus den Schritten 2-4, in der zweiten benötigen Sie ihn nur in Schritt 3. – karunski

1

aus meiner Erfahrung mit geringer Latenz Socket-Anwendungen:

für schreibt - versuchen, vom Schreiben Faden direkt in die Steckdose zu schreiben (müssen Sie Ereignisschleife Mutex dafür erhalten), wenn der Schreib unvollständig abonnieren Bereitschaft schreiben mit Ereignisschleife (select/waitformultipleobjects) und schreiben aus Ereignisschleife Thread, wenn Socket schreibbar

für liest - immer "abonniert" für Read Readiness für alle Sockets, so dass Sie immer aus innerhalb Ereignisschleife Thread lesen, wenn der Sockel bekommt lesbar