次のような側面に興味があります。
- スコープ/機能
- パフォーマンス
- 成熟
次のような側面に興味があります。
回答:
Boost.Asioは、ネットワークに重点を置いて開始されたC ++ライブラリですが、その非同期I / O機能は他のリソースにまで拡張されています。さらに、Boost.AsioはBoostライブラリの一部であるため、その範囲は他のBoostライブラリとの重複を防ぐためにわずかに狭められています。たとえば、Boost.Asioは、Boost.Threadがすでに提供しているため、スレッドの抽象化を提供しません。
一方、libuvはNode.jsのプラットフォームレイヤーとして設計されたCライブラリです。これは、抽象化のために提供してIOCP Windows上で、kqueueの MacOSの上、およびファイルディスクリプタ Linux上を。さらに、その範囲は、スレッド、スレッドプール、スレッド間通信などの抽象化と機能を含めるためにわずかに拡大されているように見えます。
コアでは、各ライブラリがイベントループと非同期I / O機能を提供します。タイマー、ソケット、非同期操作など、いくつかの基本機能が重複しています。libuvはより広い範囲を持ち、スレッドと同期の抽象化、同期および非同期のファイルシステム操作、プロセス管理などの追加機能を提供します。対照的に、Boost.Asioのオリジナルのネットワークフォーカスサーフェスは、関連するネットワークの豊富なセットを提供するため、 ICMP、SSL、同期ブロッキングおよび非ブロッキング操作などの機能、および改行が受信されるまでストリームから読み取るなど、一般的なタスクの高レベルの操作。
主な機能のいくつかを簡単に並べて比較します。Boost.Asioを使用する開発者は他のBoostライブラリを利用できることが多いため、直接提供するか、実装するのが簡単な場合は、追加のBoostライブラリを検討することにしました。
libuv Boost イベントループ:はいAsio スレッドプール:はいAsio +スレッド スレッディング: スレッド:はいスレッド 同期:はいスレッド ファイルシステム操作: 同期:はいFileSystem 非同期:はい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:はい、いいえ 共有ライブラリの読み込み:yes拡張[2]
1. 散布/ I / Oを収集します。
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
、複数のスレッドの呼び出しを許可した結果、は1つとして簡単に機能できますrun
。これは、この例でわかるように、スレッド管理と動作の責任をユーザーに課します。EAGAIN
EWOULDBLOCK
kill
そのuv_signal_t
タイプとuv_signal_*
操作による抽象化と信号処理を提供します。kill
が、signal_set
信号処理を提供します。uv_pipe_t
型で抽象化します。local::stream_protocol::socket
orとlocal::datagram_protocol::socket
、に分離しwindows::stream_handle
ます。APIは言語のみに基づいて異なりますが、いくつかの重要な違いがあります。
Boost.Asio内では、操作とハンドラーの間に1対1のマッピングがあります。たとえば、各async_write
操作はWriteHandlerを 1回呼び出します。これは、多くのlibuv操作とハンドラーに当てはまります。ただし、libuv uv_async_send
は多対1のマッピングをサポートしています。複数のuv_async_send
呼び出しを行うと、uv_async_cbが1回呼び出される場合があります。
ストリーム/ UDPからの読み取り、シグナルの処理、タイマーの待機などのタスクを処理する場合、Boost.Asioの非同期呼び出しチェーンはもう少し明示的です。libuvを使用すると、特定のイベントへの関心を示すウォッチャーが作成されます。次に、ウォッチャーのループが開始され、そこでコールバックが提供されます。関心のあるイベントを受信すると、コールバックが呼び出されます。一方、Boost.Asioでは、アプリケーションがイベントの処理に関心を持つたびに操作を発行する必要があります。
この違いを説明するために、async_receive
呼び出しが複数回発行されるBoost.Asioによる非同期読み取りループを次に示します。
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 ); --'
}
そして、これhandle_read
はlibuvを使用した同じ例です。ここでは、ウォッチャーがソケットにデータがあることを確認するたびに呼び出されます。
uv_read_start( socket, alloc_buffer, handle_read ); --.
|
.-------------------------------------------------'
|
V
void handle_read( ... )
{
fprintf( stdout, "got data\n" );
}
Boost.Asioの非同期呼び出しチェーンとlibuvのウォッチャーの結果として、多くの場合、メモリ割り当ては異なる時間に発生します。ウォッチャーを使用すると、libuvは、処理にメモリを必要とするイベントを受信するまで割り当てを延期します。割り当てはユーザーコールバックを通じて行われ、libuvの内部で呼び出され、アプリケーションの割り当て解除の責任を遅延します。一方、buffer
forの場合のように、Boost.Asio操作の多くは、非同期操作を発行する前にメモリを割り当てる必要があります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日にBoost 1.35に受け入れられました。また、TR2のネットワークライブラリプロポーザルのリファレンス実装およびAPIとしても機能しました。Boost.Asioにはかなりの量のドキュメントがありますが、その有用性はユーザーごとに異なります。
APIもかなり一貫した感覚を持っています。さらに、非同期操作は操作の名前で明示的です。たとえば、accept
は同期ブロッキングでasync_accept
あり、非同期です。APIは、一般的なI / Oタスクに無料の関数を提供します。たとえば、ストリームから\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
は、監視ループを作成することです。これは、通常、ウォッチャーループの寿命を制御する1つuv_*_start
またはuv_*_stop
2つの機能を持つ他のウォッチャーとは異なります。また、一部のuv_fs_*
操作には適切な量の引数があります(最大7)。同期動作と非同期動作がコールバック(最後の引数)の存在で決定されるため、同期動作の可視性が低下する可能性があります。
最後に、libuvのコミット履歴を一目見ると、開発者が非常に活発であることがわかります。
uv_async_send
呼び出しを蓄積し、単一のコールバックでそれらをすべて処理できます。こちらに記載されています。また、みんなに感謝します。
OK。私は両方のライブラリを使用した経験があり、いくつかのことを明確にすることができます。
まず、概念的な観点から見ると、これらのライブラリは設計がまったく異なります。規模が異なるため、アーキテクチャが異なります。Boost.Asioは、TCP / UDP / ICMPプロトコル、POSIX、SSLなどでの使用を目的とした大規模なネットワークライブラリです。Libuvは、主にNode.js用のIOCPのクロスプラットフォーム抽象化のための単なるレイヤーです。したがって、libuvは機能的にBoost.Asioのサブセットです(一般的な機能はTCP / UDPソケットスレッド、タイマーのみです)。そのため、いくつかの基準のみを使用してこれらのライブラリを比較できます。
新しいC ++機能との統合:Asioの方が優れています(Asio 1.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
移植性ステータスの追加:この回答を投稿した時点で、私自身の試みによれば: