libuvはBoost / ASIOと比較してどうですか?


239

次のような側面に興味があります。

  • スコープ/機能
  • パフォーマンス
  • 成熟

20
この質問に戻って、良い答えを得ましょう!
ベトナム

\ o / ..洞察に満ちた答えが得られることを願っています!
oberstet 2012年

回答:


493

範囲

Boost.Asioは、ネットワークに重点を置いて開始されたC ++ライブラリですが、その非同期I / O機能は他のリソースにまで拡張されています。さらに、Boost.AsioはBoostライブラリの一部であるため、その範囲は他のBoostライブラリとの重複を防ぐためにわずかに狭められています。たとえば、Boost.Asioは、Boost.Threadがすでに提供しているため、スレッドの抽象化を提供しません。

一方、libuvNode.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つの間に微妙な違いがあります。

  • libuvは複数のイベントループをサポートしていますが、複数のスレッドからの同じループの実行はサポートしていません。このため、別のコンポーネントがデフォルトループを実行している可能性があるuv_default_loop()ため、新しいループ(uv_loop_new())を作成するのではなく、デフォルトループ()を使用する場合は注意が必要です。
  • Boost.Asioにはデフォルトループの概念はありません。これらio_serviceはすべて、複数のスレッドの実行を可能にする独自のループです。このBoost.Asioをサポートするには、パフォーマンスを犠牲にして内部ロックを実行します。Boost.Asioの改訂履歴は、ロックを最小限に抑えるためにいくつかのパフォーマンスの改善があったことを示しています。

スレッドプール

  • libuvはを介してスレッドプールを提供しますuv_queue_work。スレッドプールのサイズは、環境変数を使用して構成できますUV_THREADPOOL_SIZE。作業は、イベントループの外とスレッドプール内で実行されます。作業が完了すると、完了ハンドラーがキューに入れられ、イベントループ内で実行されます。
  • Boost.Asioはスレッドプールを提供していませんio_serviceio_service、複数のスレッドの呼び出しを許可した結果、は1つとして簡単に機能できますrun。これは、この例でわかるように、スレッド管理と動作の責任をユーザーに課します。

スレッド化と同期

  • libuvは、スレッドと同期タイプの抽象化を提供します。
  • Boost.Threadは、スレッドと同期タイプを提供します。これらの型の多くはC ++ 11標準に厳密に従っていますが、いくつかの拡張機能も提供します。Boost.Asioにより複数のスレッドが単一のイベントループを実行できるようになった結果、明示的なロックメカニズムを使用せずにイベントハンドラーの順次呼び出しを作成する手段としてストランドが提供されます。

ファイルシステムの操作

  • libuvは、多くのファイルシステム操作の抽象化を提供します。操作ごとに1つの関数があり、各操作は同期ブロッキングまたは非同期のいずれかになります。コールバックが提供されている場合、操作は内部スレッドプール内で非同期的に実行されます。コールバックが提供されない場合、呼び出しは同期ブロッキングになります。
  • Boost.Filesystemは、多くのファイルシステム操作に対して同期ブロッキング呼び出しを提供します。これらをBoost.Asioおよびスレッドプールと組み合わせて、非同期ファイルシステム操作を作成できます。

ネットワーキング

  • libuvは、UDPおよびTCPソケットでの非同期操作、およびDNS解決をサポートしています。アプリケーション開発者は、基礎となるファイル記述子が非ブロッキングに設定されていることに注意する必要があります。したがって、ネイティブの同期操作では、またはの戻り値とerrnoを確認する必要がありますEAGAINEWOULDBLOCK
  • Boost.Asioは、ネットワーキングサポートがもう少し豊富です。さらに、libuvのネットワークが提供する機能の多くは、SSLおよびICMPソケットをサポートするBoost.Asioです。さらに、Boost.Asioは、非同期操作に加えて、同期ブロッキングおよび同期非ブロッキング操作を提供します。一定量のバイトの読み取りや、指定された区切り文字の読み取りなど、一般的な上位レベルの操作を提供する独立した関数が多数あります。

信号

  • libuvは、killそのuv_signal_tタイプとuv_signal_*操作による抽象化と信号処理を提供します。
  • Boost.Asioはに抽象化を提供しませんkillが、signal_set信号処理を提供します。

IPC


APIの違い

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の内部で呼び出され、アプリケーションの割り当て解除の責任を遅延します。一方、bufferforの場合のように、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では、ハンドラーのメモリ割り当て戦略を実装するために、アプリケーションでカスタムメモリ割り当て関数を提供できます。


成熟

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サポートも提供します。

libuv

それらのgithubグラフに基づいて、Node.jsの開発は少なくともFEB-2009にさかのぼり、libuvの開発はMAR-2011にさかのぼります。uvbookは libuv導入のための絶好の場所です。APIドキュメントはこちらです。

全体として、APIはかなり一貫しており、使いやすいです。混乱の原因となる可能性のある異常の1つuv_tcp_listenは、監視ループを作成することです。これは、通常、ウォッチャーループの寿命を制御する1つuv_*_startまたはuv_*_stop2つの機能を持つ他のウォッチャーとは異なります。また、一部のuv_fs_*操作には適切な量の引数があります(最大7)。同期動作と非同期動作がコールバック(最後の引数)の存在で決定されるため、同期動作の可視性が低下する可能性があります。

最後に、libuvのコミット履歴を一目見ると、開発者が非常に活発であることがわかります。


2
ありがとう!正解です。私はこれ以上包括的なものを考えることはできません:)
Viet

1
答えに非常に満足して、私はあなたに賞金を授与します:) SOに自分のための最良の答えを決定させましょう。
ベトナム、

28
信じられないほどの答え。これは、高レベルの画像だけでなく、具体的な重要な違い(つまり、スレッド化/イベントループなど)の両方をカバーします。どうもありがとうございました!
oberstet

1
@oberstet:いいえ。回答を更新して、libuvの操作のほとんどが1対1であることに言及しました。ただし、libuvは複数のuv_async_send呼び出しを蓄積し、単一のコールバックでそれらをすべて処理できます。こちらに記載されています。また、みんなに感謝します。
Tanner Sansbury、2012年

2
Boost.Asioのイベントループの内部ロックは、パフォーマンスの観点から恐ろしく見えます。ロックフリーのlibuvと同様のパフォーマンスを実現するにはどうすればよいですか?パフォーマンスセクションに警告文を追加すると役立つ場合があります。
zeodtr 2014年

46

OK。私は両方のライブラリを使用した経験があり、いくつかのことを明確にすることができます。

まず、概念的な観点から見ると、これらのライブラリは設計がまったく異なります。規模が異なるため、アーキテクチャが異なります。Boost.Asioは、TCP / UDP / ICMPプロトコル、POSIX、SSLなどでの使用を目的とした大規模なネットワークライブラリです。Libuvは、主にNode.js用のIOCPのクロスプラットフォーム抽象化のための単なるレイヤーです。したがって、libuvは機能的にBoost.Asioのサブセットです(一般的な機能はTCP / UDPソケットスレッド、タイマーのみです)。そのため、いくつかの基準のみを使用してこれらのライブラリを比較できます。

  1. Node.jsとの統合-Libuvはこれを目的としているため、かなり優れています(完全に統合して、たとえばWindows Azureなどのすべての面で使用できます)。ただし、AsioはNode.jsイベントキュー駆動環境とほぼ同じ機能を実装しています。
  2. IOCPパフォーマンス-これらのライブラリは両方とも、基盤となるOS APIを抽象化しているため、大きな違いはありませんでした。しかし、彼らは別の方法でそれを行います:Asioはテンプレートや時々TMPなどのC ++機能を頻繁に使用します。LibuvはネイティブCライブラリです。それにもかかわらず、IOCPのAsio実現は非常に効率的です。AsioのUDPソケットは十分ではないため、libuvを使用することをお勧めします。

    新しい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いくつかのビデオトークがあるため、すべての秘密を知ることは困難です(このライブラリにはたくさんの秘密があります)。関数のより具体的な説明については、以下の私のコメントを参照してください。

結論として、それはすべてあなたの目的、あなたのプロジェクト、そしてあなたが具体的に何をするつもりであるかに依存すると言っておくべきです。


11
重要なのはあなたの技術的なスキルと経験です。キューバからの親切な挨拶。
DSIGN

2
Asioのドキュメント以外のすべての点に同意します。公式ドキュメントは、この素晴らしいライブラリを正当化しません。他にもたくさんのドキュメントと筆者からのブーストコントークがあり、とても役に立ったと思います。そして、私はAsioの本に出くわしませんでした。あなたの答えにそれをリンクできますか?とても参考になります。
Vikas 2012年

@vikasはい私はドキュメントが不十分で時々矛盾していることに同意しますが、libuvと比較するとそれは始めるのにいいです。本に関しては私は私の答えを編集しますが、あなたはそれを以前に見たと思います(残念ながら、Boostに完全に専用の本はありません-散らばっている情報)
Oleksandr Karaberov

「だからlibuvは機能的にBoost.Asio(TCP / UDP /ソケットとスレッド)のサブセットです」とはどういう意味ですか?TOC nikhilm.github.com/uvbook/index.htmlによれば、libuvはより幅広いアプリケーションを持ち、boost :: asioを持っています。
セルゲイニコロフ2012年

7
@AlexanderKaraberov ASIOがUDPで抱えている問題を詳しく説明していただけますか?
Bruno Martinez


2

移植性ステータスの追加:この回答を投稿した時点で、私自身の試みによれば:

  • Boost.ASIOはiOSとAndroidを公式にサポートしていません。たとえば、ビルドシステムはそのままではiOSで機能しません。
  • libuvはiOSとAndroid向けに簡単にビルドでき、Androidの公式サポートがドキュメントに含まれています。Autotoolsベースのプロジェクト用の私自身の汎用iOSビルドスクリプトは問題なく動作します。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.