Byłbym zainteresowany takimi aspektami jak:
- zakres / funkcje
- występ
- dojrzałość
c++
boost
boost-asio
libuv
oberstet
źródło
źródło
Odpowiedzi:
Zakres
Boost.Asio to biblioteka C ++, która zaczęła się od sieci, ale jej asynchroniczne funkcje we / wy zostały rozszerzone na inne zasoby. Dodatkowo, ponieważ Boost.Asio jest częścią bibliotek Boost, jego zakres jest nieco zawężony, aby zapobiec duplikacji z innymi bibliotekami Boost. Na przykład Boost.Asio nie zapewni abstrakcji nici, ponieważ Boost.Thread już ją udostępnia.
Z drugiej strony, libuv jest biblioteką C zaprojektowany jako warstwa platforma node.js . Zapewnia abstrakcję dla IOCP w systemie Windows, kqueue na macOS i epoll w systemie Linux. Dodatkowo wygląda na to, że jego zakres nieznacznie się zwiększył, włączając abstrakcje i funkcje, takie jak wątki, pule wątków i komunikacja między wątkami.
U podstaw każdej biblioteki znajduje się pętla zdarzeń i asynchroniczne funkcje we / wy. Nakładają się na siebie niektóre podstawowe funkcje, takie jak liczniki czasu, gniazda i operacje asynchroniczne. libuv ma szerszy zakres i zapewnia dodatkowe funkcje, takie jak abstrakcje wątków i synchronizacji, synchroniczne i asynchroniczne operacje na systemie plików, zarządzanie procesami itp. W przeciwieństwie do tego, pierwotne ukierunkowanie sieciowe Boost.Asio, ponieważ zapewnia bogatszy zestaw powiązanych z siecią możliwości, takie jak ICMP, SSL, synchroniczne operacje blokowania i nieblokowania oraz operacje wyższego poziomu do typowych zadań, w tym odczytywanie ze strumienia do momentu otrzymania nowej linii.
Lista funkcji
Oto krótkie porównanie niektórych głównych funkcji. Ponieważ programiści używający Boost.Asio często dysponują innymi bibliotekami Boost, zdecydowałem się rozważyć dodatkowe biblioteki Boost, jeśli są one dostarczane bezpośrednio lub są trywialne do wdrożenia.
1. rozproszony / Zebrać I / O .
2. Zwiększenie . Rozszerzenie nigdy nie zostało przesłane do oceny w ramach wzmocnienia. Jak wspomniano tutaj , autor uważa to za kompletne.
Pętla zdarzeń
Chociaż zarówno libuv, jak i Boost.Asio zapewniają pętle zdarzeń, istnieją między nimi pewne subtelne różnice:
uv_default_loop()
), zamiast tworzyć nową pętlę (uv_loop_new()
), ponieważ inny komponent może uruchamiać domyślną pętlę.io_service
są własnymi pętlami, które pozwalają na uruchomienie wielu wątków. Aby wesprzeć ten Boost.Asio wykonuje wewnętrzne blokowanie kosztem pewnej wydajności . Historia wersji Boost.Asio wskazuje, że wprowadzono kilka ulepszeń wydajności w celu zminimalizowania blokowania.Pula wątków
uv_queue_work
. Rozmiar puli wątków można konfigurować za pomocą zmiennej środowiskowejUV_THREADPOOL_SIZE
. Praca zostanie wykonana poza pętlą zdarzeń i w puli wątków. Po zakończeniu pracy moduł obsługi zakończenia będzie w kolejce do uruchomienia w pętli zdarzeń.io_service
może z łatwością działać jako jeden, ponieważio_service
pozwala na wywołanie wielu wątkówrun
. To nakłada na użytkownika odpowiedzialność za zarządzanie wątkami i ich zachowanie, co można zobaczyć w tym przykładzie.Wątek i synchronizacja
Operacje systemu plików
Networking
EAGAIN
lubEWOULDBLOCK
.Sygnał
kill
i obsługę sygnałów z ichuv_signal_t
rodzajem iuv_signal_*
działaniem.kill
, alesignal_set
zapewnia obsługę sygnału.IPC
uv_pipe_t
typu.local::stream_protocol::socket
lublocal::datagram_protocol::socket
, iwindows::stream_handle
.Różnice API
Chociaż interfejsy API różnią się w zależności od samego języka, oto kilka kluczowych różnic:
Stowarzyszenie Operacji i Handlerów
W ramach Boost.Asio istnieje odwzorowanie jeden na jednego między operacją a modułem obsługi. Na przykład każda
async_write
operacja wywoła WriteHandler jeden raz. Dotyczy to wielu operacji i programów obsługi libuv. Jednak libuvuv_async_send
obsługuje mapowanie wiele do jednego. Wieleuv_async_send
wywołań może spowodować, że uv_async_cb zostanie wywołany jeden raz.Łańcuchy połączeń vs. Pętle obserwatora
W przypadku zadań, takich jak odczyt ze strumienia / UDP, obsługa sygnałów lub oczekiwanie na liczniki czasu, asynchroniczne łańcuchy połączeń Boost.Asio są nieco bardziej wyraźne. W libuv tworzony jest obserwator, który określa zainteresowania w konkretnym wydarzeniu. Następnie uruchamiana jest pętla dla obserwatora, w której zapewnione jest wywołanie zwrotne. Po otrzymaniu zdarzenia zainteresowania zostanie wywołane oddzwonienie. Z drugiej strony Boost.Asio wymaga wykonania operacji za każdym razem, gdy aplikacja jest zainteresowana obsługą zdarzenia.
Aby zilustrować tę różnicę, oto asynchroniczna pętla odczytu z funkcją Boost.Asio, w której
async_receive
wywołanie zostanie wykonane wielokrotnie:A oto ten sam przykład z libuv, gdzie
handle_read
jest wywoływany za każdym razem, gdy obserwator zauważy, że gniazdo ma dane:Przydział pamięci
W wyniku asynchronicznych łańcuchów wywołań w Boost.Asio i obserwatorów w libuv alokacja pamięci często występuje w różnych momentach. W przypadku obserwatorów libuv odkłada alokację, dopóki nie otrzyma zdarzenia wymagającego pamięci do obsługi. Alokacja odbywa się poprzez wywołanie zwrotne użytkownika, wywoływane wewnętrznie w libuv i odracza odpowiedzialność aplikacji za dezalokację. Z drugiej strony wiele operacji Boost.Asio wymaga przydzielenia pamięci przed wykonaniem operacji asynchronicznej, na przykład w przypadku
buffer
forasync_read
. Boost.Asio zapewnianull_buffers
, że można go użyć do nasłuchiwania zdarzenia, umożliwiając aplikacjom odraczanie alokacji pamięci do momentu, gdy pamięć będzie potrzebna, chociaż jest to przestarzałe.Ta różnica alokacji pamięci pojawia się również w
bind->listen->accept
pętli. W libuvuv_listen
tworzy pętlę zdarzeń, która wywoła oddzwonienie użytkownika, gdy połączenie będzie gotowe do zaakceptowania. Umożliwia to aplikacji odroczenie alokacji klienta do momentu próby nawiązania połączenia. Z drugiej strony Boost.Asiolisten
zmienia tylko stanacceptor
. Wasync_accept
nasłuchuje przypadku połączenia, a wymaga peer to być przydzielane przed wywoływany.Występ
Niestety nie mam konkretnych liczb porównawczych do porównania libuv i Boost.Asio. Jednak zaobserwowałem podobną wydajność przy użyciu bibliotek w aplikacjach w czasie rzeczywistym i prawie w czasie rzeczywistym. Jeśli pożądane są liczby twarde, punktem odniesienia może być test porównawczy libuv .
Ponadto, mimo że należy przeprowadzić profilowanie w celu zidentyfikowania faktycznych wąskich gardeł, należy pamiętać o przydziałach pamięci. W przypadku libuv strategia alokacji pamięci ogranicza się przede wszystkim do wywołania zwrotnego alokatora. Z drugiej strony, API Boost.Asio nie pozwala na wywołanie zwrotne alokatora, a zamiast tego wypycha strategię alokacji do aplikacji. Jednak procedury obsługi / wywołania zwrotne w Boost.Asio mogą być kopiowane, przydzielane i zwalniane. Boost.Asio pozwala aplikacjom na zapewnienie niestandardowych funkcji alokacji pamięci w celu zaimplementowania strategii alokacji pamięci dla programów obsługi.
Dojrzałość
Boost.Asio
Rozwój Asio sięga co najmniej OCT-2004 i został przyjęty do Boost 1.35 22-MAR-2006 po przejściu 20-dniowej wzajemnej oceny. Służył również jako implementacja referencyjna i API dla Networking Library Propission for TR2 . Boost.Asio ma sporo dokumentacji , chociaż jego użyteczność różni się w zależności od użytkownika.
Interfejs API ma również dość spójne działanie. Ponadto operacje asynchroniczne są jawne w nazwie operacji. Na przykład
accept
blokuje synchronicznie iasync_accept
jest asynchroniczny. Interfejs API zapewnia bezpłatne funkcje do typowych zadań we / wy, na przykład czytanie ze strumienia, aż do\r\n
odczytu. Zwrócono również uwagę na ukrycie niektórych szczegółów dotyczących sieci, takich jakip::address_v4::any()
reprezentacja adresu „wszystkich interfejsów”0.0.0.0
.Wreszcie, Boost 1.47+ zapewnia śledzenie procedur obsługi , które mogą okazać się przydatne podczas debugowania, a także obsługę C ++ 11.
libuv
Na podstawie ich wykresów github rozwój Node.js sięga co najmniej FEB-2009 , a rozwój libuv - MAR-2011 . Książka uvbook to świetne miejsce na wprowadzenie libuv. Dokumentacja API jest tutaj .
Ogólnie rzecz biorąc, interfejs API jest dość spójny i łatwy w użyciu. Jedną z anomalii, które mogą być źródłem nieporozumień, jest
uv_tcp_listen
tworzenie pętli obserwatora. Jest to inaczej niż w innych obserwatorów, które mają zwykleuv_*_start
iuv_*_stop
parę funkcji kontrolowania trwałości pętli obserwatora. Ponadto niektóreuv_fs_*
operacje mają przyzwoitą liczbę argumentów (do 7). Dzięki określeniu zachowania synchronicznego i asynchronicznego na podstawie wywołania zwrotnego (ostatniego argumentu) widoczność zachowania synchronicznego może zostać zmniejszona.Wreszcie, szybkie spojrzenie na historię zatwierdzania libuv pokazuje, że programiści są bardzo aktywni.
źródło
uv_async_send
połączeń i obsługiwać je wszystkie za pomocą jednego połączenia zwrotnego. Jest to udokumentowane tutaj . Dziękuję również wszystkim.Dobrze. Mam pewne doświadczenie w korzystaniu z obu bibliotek i potrafię wyjaśnić niektóre rzeczy.
Po pierwsze, z koncepcyjnego punktu widzenia biblioteki te mają zupełnie inną budowę. Mają różne architektury, ponieważ mają różną skalę. Boost.Asio to duża biblioteka sieciowa przeznaczona do użycia z protokołami TCP / UDP / ICMP, POSIX, SSL i tak dalej. Libuv to przede wszystkim warstwa do wieloplatformowej abstrakcji IOCP dla Node.js. Tak więc libuv jest funkcjonalnie podzbiorem Boost.Asio (wspólne funkcje tylko wątki TCP / UDP Sockets, timery). W takim przypadku możemy porównać te biblioteki przy użyciu tylko kilku kryteriów:
Integracja z nowymi funkcjami C ++: Asio jest lepsze (Asio 1.51 intensywnie korzysta z modelu asynchronicznego C ++ 11, semantyki przenoszenia, szablonów variadic). Pod względem dojrzałości Asio jest bardziej stabilnym i dojrzałym projektem z dobrą dokumentacją (jeśli porównać go z libuv opis nagłówków), wiele informacji w Internecie (rozmowy wideo, blogi: http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting-started-with-boostasio?pg = 1 itd.), A nawet książki (nie dla profesjonalistów, ale mimo to: http://en.highscore.de/cpp/boost/index.html ). Libuv ma tylko jedną książkę online (ale także dobrą) http://nikhilm.github.com/uvbook/index.htmli kilka rozmów wideo, więc trudno będzie poznać wszystkie sekrety (ta biblioteka ma ich wiele). Aby uzyskać bardziej szczegółowe omówienie funkcji, zobacz moje komentarze poniżej.
Podsumowując, powinienem powiedzieć, że wszystko zależy od twoich celów, twojego projektu i tego, co konkretnie zamierzasz zrobić.
źródło
Ogromną różnicą jest to, że autor Asio (Christopher Kohlhoff) przygotowuje swoją bibliotekę do włączenia do standardowej biblioteki C ++, patrz http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2175 .pdf i http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4370.html
źródło
Dodanie statusu przenośności: od opublikowania tej odpowiedzi i zgodnie z moimi próbami:
źródło