私は次のような側面に興味があります:
- スコープ/機能
- パフォーマンス
- 成熟
Boost.Asioはネットワーキングに重点を置いて開始されたC++ライブラリですが、その非同期I/O機能は他のリソースに拡張されています。さらに、Boost.AsioはBoostライブラリの一部であるため、他のBoostライブラリとの重複を防ぐために、その範囲はわずかに狭くなっています。たとえば、Boost.Threadはすでにスレッド抽象化を提供しているため、Boost.Asioはスレッド抽象化を提供しません。
一方、libuvは、 Node.jsのプラットフォームレイヤーとして設計されたCライブラリです。これは、 WindowsではIOCP、macOSではkqueue 、Linuxではepollの抽象化を提供します。さらに、その範囲がわずかに拡大して、スレッド、スレッドプール、スレッド間通信などの抽象化と機能が含まれているように見えます。
基本的に、各ライブラリはイベントループと非同期I/O機能を提供します。これらは、タイマー、ソケット、非同期操作などの基本機能の一部で重複しています。libuvはより広い範囲を持ち、スレッドと同期の抽象化、同期および非同期のファイルシステム操作、プロセス管理などの追加機能を提供します。対照的に、Boost.Asioの元のネットワークフォーカスサーフェスは、ネットワーク関連の豊富なセットを提供します。 ICMP、SSL、同期ブロッキングおよび非ブロッキング操作などの機能、および新しい行が受信されるまでのストリームからの読み取りを含む、一般的なタスクの高レベルの操作。
これは、いくつかの主要な機能を並べて比較したものです。Boost.Asioを使用している開発者は、他のBoostライブラリを利用できることが多いため、直接提供されているか、実装が簡単な場合は、追加のBoostライブラリを検討することにしました。
libuv Boost イベントループ:はいAsio スレッドプール:はいAsio+スレッド 糸脱毛: スレッド:はいスレッド 同期:はいスレッド ファイルシステムの操作: 同期:はいファイルシステム 非同期:はいAsio+ファイルシステム タイマー:はいAsio Scatter / Gather I / O [1]:Asioなし ネットワーキング: ICMP:Asioなし DNS解決:非同期のみのAsio SSL:Asioなし TCP:非同期のみのAsio UDP:非同期のみのAsio 信号: 取り扱い:はいAsio 送信:はいいいえ IPC: UNIXドメインソケット:はいAsio Windows名前付きパイプ:はいAsio プロセス管理: 切り離し:はいプロセス I / Oパイプ:はいプロセス 産卵:はいプロセス システムクエリ: CPU:はいいいえ ネットワークインターフェース:はいいいえ シリアルポート:いいえはい TTY:はいいいえ 共有ライブラリの読み込み:はい拡張機能[2]
2. Boost.Extensionは、Boostへのレビューのために送信されたことはありません。ここで述べたように、作者はそれが完全であると考えています。
libuvとBoost.Asioはどちらもイベントループを提供しますが、2つの間にいくつかの微妙な違いがあります。
uv_default_loop()
、新しいループ()を作成するのではなく、デフォルトループ()を使用する場合は注意が必要です。uv_loop_new()
io_service
が独自のループであり、複数のスレッドを実行できます。このBoost.Asioをサポートするために、パフォーマンスをいくらか犠牲にして内部ロックを実行します。Boost.Asioの改訂履歴は、ロックを最小限に抑えるためにいくつかのパフォーマンスの改善があったことを示しています。uv_queue_work
。スレッドプールのサイズは、環境変数を介して構成できますUV_THREADPOOL_SIZE
。作業は、イベントループの外部およびスレッドプール内で実行されます。作業が完了すると、完了ハンドラーはイベントループ内で実行するためにキューに入れられます。io_service
を許可した結果、はスレッドプールとして簡単に機能できます。これにより、この例に示すように、スレッドの管理と動作の責任がユーザーに課せられます。io_service
run
EAGAIN
EWOULDBLOCK
kill
と信号処理を提供します。uv_signal_t
uv_signal_*
kill
が、signal_set
信号処理を提供します。uv_pipe_t
タイプで抽象化します。local::stream_protocol::socket
または、、local::datagram_protocol::socket
およびに分離しwindows::stream_handle
ます。APIは言語のみに基づいて異なりますが、いくつかの重要な違いがあります。
Boost.Asio内には、操作とハンドラーの間に1対1のマッピングがあります。たとえば、各async_write
操作はWriteHandlerを1回呼び出します。これは、多くのlibuv操作とハンドラーに当てはまります。ただし、libuvuv_async_send
は多対1のマッピングをサポートしています。複数uv_async_send
の呼び出しにより、uv_async_cbが1回呼び出される場合があります。
ストリーム/UDPからの読み取り、シグナルの処理、タイマーの待機などのタスクを処理する場合、Boost.Asioの非同期呼び出しチェーンはもう少し明確です。libuvを使用すると、特定のイベントへの関心を指定するウォッチャーが作成されます。次に、ウォッチャーのループが開始され、コールバックが提供されます。関心のあるイベントを受信すると、コールバックが呼び出されます。一方、Boost.Asioでは、アプリケーションがイベントの処理に関心を持つたびに操作を発行する必要があります。
この違いを説明するために、Boost.Asioを使用した非同期読み取りループを示します。この場合、async_receive
呼び出しは複数回発行されます。
void start()
{
socket.async_receive( buffer, handle_read ); ----.
} |
.----------------------------------------------'
| .---------------------------------------.
V V |
void handle_read( ... ) |
{ |
std::cout << "got data" << std::endl; |
socket.async_receive( buffer, handle_read ); --'
}
そして、これはlibuvの同じ例です。ここではhandle_read
、ウォッチャーがソケットにデータがあることを確認するたびに呼び出されます。
uv_read_start( socket, alloc_buffer, handle_read ); --.
|
.-------------------------------------------------'
|
V
void handle_read( ... )
{
fprintf( stdout, "got data\n" );
}
Boost.Asioの非同期呼び出しチェーンとlibuvのウォッチャーの結果として、メモリ割り当ては多くの場合、異なる時間に発生します。ウォッチャーの場合、libuvは、処理にメモリを必要とするイベントを受信するまで、割り当てを延期します。割り当てはユーザーコールバックを介して行われ、libuvの内部で呼び出され、アプリケーションの割り当て解除の責任を延期します。一方、Boost.Asio操作の多くは、buffer
forの場合のように、非同期操作を発行する前にメモリを割り当てる必要がありますasync_read
。Boost.Asioはnull_buffers
、イベントをリッスンするために使用できるを提供します。これにより、アプリケーションはメモリが必要になるまでメモリ割り当てを延期できますが、これは非推奨です。
bind->listen->accept
このメモリ割り当ての違いは、ループ内にも現れます。libuvをuv_listen
使用して、接続を受け入れる準備ができたときにユーザーコールバックを呼び出すイベントループを作成します。これにより、アプリケーションは、接続が試行されるまでクライアントの割り当てを延期できます。一方、Boost.Asioはのlisten
状態を変更するだけacceptor
です。接続イベントをリッスンし、async_accept
呼び出される前にピアを割り当てる必要があります。
残念ながら、libuvとBoost.Asioを比較するための具体的なベンチマーク数はありません。ただし、リアルタイムおよびほぼリアルタイムのアプリケーションでライブラリを使用すると、同様のパフォーマンスが見られます。難しい数値が必要な場合は、libuvのベンチマークテストが出発点として役立つ場合があります。
さらに、実際のボトルネックを特定するためにプロファイリングを実行する必要がありますが、メモリの割り当てに注意してください。libuvの場合、メモリ割り当て戦略は主にアロケータコールバックに限定されます。一方、Boost.AsioのAPIは、アロケーターコールバックを許可せず、代わりに割り当て戦略をアプリケーションにプッシュします。ただし、Boost.Asioのハンドラー/コールバックは、コピー、割り当て、および割り当て解除される場合があります。Boost.Asioを使用すると、アプリケーションは、ハンドラーのメモリ割り当て戦略を実装するために、カスタムメモリ割り当て機能を提供できます。
Asioの開発は少なくともOCT-2004にまでさかのぼり、20日間のピアレビューを受けた後、2006年3月22日にBoost1.35に受け入れられました。また、TR2のネットワーキングライブラリ提案のリファレンス実装およびAPIとしても機能しました。Boost.Asioにはかなりの量のドキュメントがありますが、その有用性はユーザーによって異なります。
APIもかなり一貫した感触を持っています。さらに、非同期操作は操作の名前で明示されています。たとえば、accept
は同期ブロッキングであり、async_accept
非同期です。APIは、一般的なI / Oタスクに無料の機能を提供します。たとえば、ストリームからの読み取りからa\r\n
が読み取られるまでです。ip::address_v4::any()
の「すべてのインターフェース」アドレスを表すなど、ネットワーク固有の詳細を非表示にすることにも注意が払われています0.0.0.0
。
最後に、Boost 1.47+は、C ++ 11のサポートだけでなく、デバッグ時に役立つことが証明できるハンドラー追跡を提供します。
githubグラフに基づくと、Node.jsの開発は少なくともFEB-2009にさかのぼり、libuvの開発はMAR-2011にさかのぼります。uvbookは、libuvを紹介するのに最適な場所です。APIドキュメントはこちらです。
全体として、APIはかなり一貫性があり、使いやすいです。混乱の原因となる可能性のある異常の1つuv_tcp_listen
は、ウォッチャーループを作成することです。これは、ウォッチャーループの寿命を制御するための関数と関数のペアを一般的uv_*_start
に備えている他のウォッチャーとは異なります。uv_*_stop
また、一部のuv_fs_*
操作には、適切な量の引数(最大7つ)があります。コールバック(最後の引数)の存在に基づいて同期および非同期の動作が決定されると、同期の動作の可視性が低下する可能性があります。
最後に、libuvコミット履歴をざっと見ると、開発者が非常にアクティブであることがわかります。
Ok。私は両方のライブラリを使用した経験があり、いくつかのことを明確にすることができます。
まず、概念的な観点から、これらのライブラリは設計がまったく異なります。規模が異なるため、アーキテクチャも異なります。Boost.Asioは、TCP / UDP / ICMPプロトコル、POSIX、SSLなどで使用することを目的とした大規模なネットワークライブラリです。Libuvは、主にNode.jsのIOCPのクロスプラットフォーム抽象化のための単なるレイヤーです。したがって、libuvは機能的にBoost.Asioのサブセットです(共通の機能はTCP / UDPソケットスレッド、タイマーのみです)。その場合、いくつかの基準を使用してこれらのライブラリを比較できます。
新しいC++機能との統合:Asioの方が優れています(Asio1.51はC++ 11非同期モデル、移動セマンティクス、可変個引数テンプレートを幅広く使用しています)成熟度に関しては、Asioはより安定した成熟したプロジェクトであり、優れたドキュメントを備えています(libuvと比較した場合)ヘッダーの説明)、インターネット全体の多くの情報(ビデオトーク、ブログ:http ://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting-started-with-boostasio?pg = 1など)および本(専門家向けではありませんが、それでもhttp://en.highscore.de/cpp/boost/index.html)。Libuvにはオンラインブックが1冊しかありません(ただし、良い本もあります)http://nikhilm.github.com/uvbook/index.htmlいくつかのビデオトークがあるので、すべての秘密を知ることは難しいでしょう(このライブラリにはたくさんの秘密があります)。関数のより具体的な議論については、以下の私のコメントを参照してください。
結論として、それはすべてあなたの目的、あなたのプロジェクト、そしてあなたが具体的に何をしようとしているのかに依存していると言わなければなりません。
大きな違いの1つは、Asio(Christopher Kohlhoff)の作成者がC++標準ライブラリに含めるためにライブラリをグルーミングしていることです。http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2175を参照してください。 .pdfおよびhttp://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4370.html
移植性ステータスの追加:この回答を投稿した時点で、私自身の試みによると: