Ich würde mich für Aspekte interessieren wie:
- Umfang / Funktionen
- Performance
- Reife
c++
boost
boost-asio
libuv
oberstet
quelle
quelle
Antworten:
Umfang
Boost.Asio ist eine C ++ - Bibliothek, die mit dem Schwerpunkt Netzwerk begann. Die asynchronen E / A-Funktionen wurden jedoch auf andere Ressourcen erweitert. Da Boost.Asio Teil der Boost-Bibliotheken ist, wird der Umfang geringfügig eingeschränkt, um Doppelungen mit anderen Boost-Bibliotheken zu vermeiden. Beispielsweise stellt Boost.Asio keine Thread-Abstraktion bereit , da Boost.Thread bereits eine bereitstellt.
Andererseits ist libuv eine C-Bibliothek, die als Plattformschicht für Node.js konzipiert wurde . Es bietet eine Abstraktion für IOCP unter Windows, kqueue unter macOS und epoll unter Linux. Darüber hinaus sieht es so aus, als ob der Umfang geringfügig zugenommen hat, um Abstraktionen und Funktionen wie Threads, Threadpools und Kommunikation zwischen Threads einzuschließen.
Im Kern bietet jede Bibliothek eine Ereignisschleife und asynchrone E / A-Funktionen. Sie überschneiden sich mit einigen grundlegenden Funktionen wie Timern, Sockets und asynchronen Vorgängen. libuv hat einen breiteren Anwendungsbereich und bietet zusätzliche Funktionen wie Thread- und Synchronisationsabstraktionen, synchrone und asynchrone Dateisystemoperationen, Prozessmanagement usw. Im Gegensatz dazu bietet Boost.Asios ursprünglicher Netzwerkfokus Oberflächen, da es eine größere Anzahl netzwerkbezogener Funktionen bietet Funktionen wie ICMP, SSL, synchrone blockierende und nicht blockierende Vorgänge sowie übergeordnete Vorgänge für allgemeine Aufgaben, einschließlich Lesen aus einem Stream bis zum Empfang einer neuen Zeile.
Funktionsliste
Hier ist der kurze Vergleich einiger wichtiger Funktionen nebeneinander. Da Entwickler, die Boost.Asio verwenden, häufig andere Boost-Bibliotheken zur Verfügung haben, habe ich mich dafür entschieden, zusätzliche Boost-Bibliotheken in Betracht zu ziehen, wenn diese entweder direkt bereitgestellt oder einfach zu implementieren sind.
1. E / A streuen / sammeln .
2. Boost.Extension wurde Boost nie zur Überprüfung vorgelegt. Wie hier erwähnt , hält der Autor es für vollständig.
Ereignisschleife
Während sowohl libuv als auch Boost.Asio Ereignisschleifen bereitstellen, gibt es einige subtile Unterschiede zwischen den beiden:
uv_default_loop()
) vorsichtig vorgegangen werden , anstatt eine neue Schleife (uv_loop_new()
) zu erstellen , da möglicherweise eine andere Komponente die Standardschleife ausführt.io_service
sind ihre eigenen Schleifen, mit denen mehrere Threads ausgeführt werden können. Um dies zu unterstützen, führt Boost.Asio eine interne Sperrung auf Kosten einer gewissen Leistung durch . Boost.Asio die Revisionsgeschichte zeigt , dass es wurden Verbesserungen mehrere Leistung die Verriegelung zu minimieren.Threadpool
uv_queue_work
. Die Threadpoolgröße kann über die Umgebungsvariable konfiguriert werdenUV_THREADPOOL_SIZE
. Die Arbeit wird außerhalb der Ereignisschleife und innerhalb des Threadpools ausgeführt. Sobald die Arbeit abgeschlossen ist, wird der Abschlusshandler in die Warteschlange gestellt, damit er innerhalb der Ereignisschleife ausgeführt werden kann.io_service
kann dieser problemlos als einer fungieren, daio_service
mehrere Threads aufgerufen werden könnenrun
. Dies überträgt dem Benutzer die Verantwortung für die Thread-Verwaltung und das Thread-Verhalten, wie in diesem Beispiel zu sehen ist .Threading und Synchronisation
Dateisystemoperationen
Vernetzung
EAGAIN
oder überprüfenEWOULDBLOCK
.Signal
kill
und Signalverarbeitung mituv_signal_t
Typ unduv_signal_*
Operationen.kill
,signal_set
bietet aber Signalverarbeitung.IPC
uv_pipe_t
Typ.local::stream_protocol::socket
oderlocal::datagram_protocol::socket
, undwindows::stream_handle
.API-Unterschiede
Während sich die APIs nur aufgrund der Sprache unterscheiden, gibt es hier einige wesentliche Unterschiede:
Operation and Handler Association
In Boost.Asio gibt es eine Eins-zu-Eins-Zuordnung zwischen einer Operation und einem Handler. Beispielsweise ruft jede
async_write
Operation den WriteHandler einmal auf. Dies gilt für viele libuv-Operationen und -Handler. Libuvsuv_async_send
unterstützt jedoch eine Viele-zu-Eins-Zuordnung. Mehrereuv_async_send
Aufrufe können dazu führen, dass uv_async_cb einmal aufgerufen wird.Call Chains vs. Watcher Loops
Bei Aufgaben wie dem Lesen aus einem Stream / UDP, dem Verarbeiten von Signalen oder dem Warten auf Timer sind die asynchronen Aufrufketten von Boost.Asio etwas expliziter. Mit libuv wird ein Beobachter erstellt, um Interessen an einem bestimmten Ereignis zu bestimmen. Anschließend wird eine Schleife für den Beobachter gestartet, in der ein Rückruf bereitgestellt wird. Nach Erhalt des Interessenereignisses wird der Rückruf aufgerufen. Auf der anderen Seite erfordert Boost.Asio, dass jedes Mal eine Operation ausgegeben wird, wenn die Anwendung an der Behandlung des Ereignisses interessiert ist.
Um diesen Unterschied zu veranschaulichen, gibt es hier eine asynchrone Leseschleife mit Boost.Asio, in der der
async_receive
Aufruf mehrmals ausgegeben wird:Und hier ist das gleiche Beispiel mit libuv, bei dem
handle_read
jedes Mal aufgerufen wird, wenn der Beobachter feststellt, dass der Socket Daten enthält:Speicherzuweisung
Aufgrund der asynchronen Aufrufketten in Boost.Asio und der Beobachter in libuv erfolgt die Speicherzuweisung häufig zu unterschiedlichen Zeiten. Bei Beobachtern verschiebt libuv die Zuordnung, bis ein Ereignis empfangen wird, für dessen Verarbeitung Speicher erforderlich ist. Die Zuweisung erfolgt über einen Benutzerrückruf, der intern in libuv aufgerufen wird, und verschiebt die Freigabeverantwortung der Anwendung. Andererseits erfordern viele der Boost.Asio-Operationen, dass der Speicher zugewiesen wird, bevor die asynchrone Operation ausgegeben wird, wie im Fall des
buffer
forasync_read
. Boost.Asio bietet die Möglichkeitnull_buffers
, auf ein Ereignis zu warten , sodass Anwendungen die Speicherzuweisung verschieben können, bis Speicher benötigt wird, obwohl dies veraltet ist.Dieser Speicherzuordnungsunterschied zeigt sich auch innerhalb der
bind->listen->accept
Schleife. Erstellt mit libuvuv_listen
eine Ereignisschleife, die den Benutzerrückruf aufruft, wenn eine Verbindung zur Annahme bereit ist. Dadurch kann die Anwendung die Zuordnung des Clients verschieben, bis eine Verbindung versucht wird. Auf der anderen Seitelisten
ändert Boost.Asio nur den Status desacceptor
. Dasasync_accept
wartet auf das Verbindungsereignis und erfordert, dass der Peer zugewiesen wird, bevor er aufgerufen wird.Performance
Leider habe ich keine konkreten Benchmark-Zahlen, um libuv und Boost.Asio zu vergleichen. Ich habe jedoch eine ähnliche Leistung bei Verwendung der Bibliotheken in Echtzeit- und Echtzeitanwendungen beobachtet. Wenn harte Zahlen gewünscht werden, kann der Benchmark-Test von libuv als Ausgangspunkt dienen.
Während die Profilerstellung durchgeführt werden sollte, um tatsächliche Engpässe zu identifizieren, sollten Sie außerdem die Speicherzuweisungen berücksichtigen. Für libuv ist die Speicherzuweisungsstrategie hauptsächlich auf den Allokator-Rückruf beschränkt. Auf der anderen Seite erlaubt die Boost.Asio-API keinen Allokator-Rückruf und überträgt stattdessen die Allokationsstrategie an die Anwendung. Die Handler / Rückrufe in Boost.Asio können jedoch kopiert, zugewiesen und freigegeben werden. Mit Boost.Asio können Anwendungen benutzerdefinierte Speicherzuweisungsfunktionen bereitstellen , um eine Speicherzuweisungsstrategie für Handler zu implementieren.
Reife
Boost.Asio
Die Entwicklung von Asio geht mindestens auf das OKT-2004 zurück und wurde am 22. März 2006 nach einer 20-tägigen Peer-Review in Boost 1.35 aufgenommen. Es diente auch als Referenzimplementierung und API für den Vorschlag für eine Netzwerkbibliothek für TR2 . Boost.Asio verfügt über eine beträchtliche Menge an Dokumentation , obwohl seine Nützlichkeit von Benutzer zu Benutzer unterschiedlich ist.
Die API hat auch ein ziemlich konsistentes Gefühl. Darüber hinaus sind die asynchronen Operationen im Namen der Operation explizit. Zum Beispiel
accept
ist synchrones Blockieren undasync_accept
ist asynchron. Die API bietet kostenlose Funktionen für allgemeine E / A-Aufgaben, z. B. Lesen aus einem Stream bis zum Lesen von a\r\n
. Es wurde auch darauf geachtet, einige netzwerkspezifische Details zu verbergen, z. B. dieip::address_v4::any()
Darstellung der Adresse "Alle Schnittstellen" von0.0.0.0
.Schließlich bietet Boost 1.47+ Handler-Tracking , das sich beim Debuggen als nützlich erweisen kann, sowie C ++ 11-Unterstützung.
libuv
Basierend auf ihren Github-Diagrammen geht die Entwicklung von Node.js auf mindestens FEB-2009 und die Entwicklung von libuv auf MAR-2011 zurück . Das uvbook ist ein großartiger Ort für eine libuv-Einführung. Die API-Dokumentation finden Sie hier .
Insgesamt ist die API ziemlich konsistent und einfach zu bedienen. Eine Anomalie, die Verwirrung stiften kann, besteht darin, dass
uv_tcp_listen
eine Überwachungsschleife erstellt wird. Dies unterscheidet sich von anderen Beobachtern, die im Allgemeinen einuv_*_start
unduv_*_stop
zwei Funktionen zur Steuerung der Lebensdauer der Überwachungsschleife haben. Außerdem haben einige deruv_fs_*
Operationen eine anständige Anzahl von Argumenten (bis zu 7). Wenn das synchrone und asynchrone Verhalten bei Vorhandensein eines Rückrufs (dem letzten Argument) bestimmt wird, kann die Sichtbarkeit des synchronen Verhaltens verringert werden.Ein kurzer Blick auf den libuv- Commit-Verlauf zeigt schließlich, dass die Entwickler sehr aktiv sind.
quelle
uv_async_send
Anrufe akkumulieren und alle mit einem einzigen Rückruf bearbeiten. Es ist hier dokumentiert . Vielen Dank auch an alle.OK. Ich habe einige Erfahrung in der Verwendung beider Bibliotheken und kann einige Dinge klären.
Erstens sind diese Bibliotheken konzeptionell sehr unterschiedlich im Design. Sie haben unterschiedliche Architekturen, weil sie unterschiedlich groß sind. Boost.Asio ist eine große Netzwerkbibliothek zur Verwendung mit TCP / UDP / ICMP-Protokollen, POSIX, SSL usw. Libuv ist nur eine Ebene für die plattformübergreifende Abstraktion von IOCP für Node.js. Libuv ist also funktional eine Teilmenge von Boost.Asio (gemeinsame Funktionen nur TCP / UDP-Sockets-Threads, Timer). In diesem Fall können wir diese Bibliotheken anhand weniger Kriterien vergleichen:
Integration mit neuen C ++ - Funktionen: Asio ist besser (Asio 1.51 verwendet ausgiebig asynchrones C ++ 11-Modell, Verschiebungssemantik, variable Vorlagen). In Bezug auf die Reife ist Asio ein stabileres und ausgereifteres Projekt mit guter Dokumentation (im Vergleich zu libuv Header-Beschreibung), viele Informationen im Internet (Videogespräche, Blogs: http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting-started-with-boostasio?pg = 1 usw.) Und sogar Bücher (nicht für Profis, aber dennoch: http://en.highscore.de/cpp/boost/index.html ). Libuv hat nur ein Online-Buch (aber auch gut) http://nikhilm.github.com/uvbook/index.htmlund mehrere Videogespräche, so dass es schwierig sein wird, alle Geheimnisse zu kennen (diese Bibliothek hat viele davon). Für eine genauere Diskussion der Funktionen siehe meine Kommentare unten.
Abschließend sollte ich sagen, dass alles von Ihren Zwecken, Ihrem Projekt und dem abhängt, was Sie konkret vorhaben.
quelle
Ein großer Unterschied besteht darin, dass der Autor von Asio (Christopher Kohlhoff) seine Bibliothek auf Aufnahme in die C ++ - Standardbibliothek vorbereitet (siehe http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2175) .pdf und http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4370.html
quelle
Hinzufügen des Portabilitätsstatus: Zum Zeitpunkt der Veröffentlichung dieser Antwort und nach meinen eigenen Versuchen:
quelle