NIES - 白線オール このページをアンテナに追加 RSSフィード

2011 | 07 |
2012 | 12 |

2012-12-19 Boost.Asioと非同期ノンブロッキングFuture

Boost.Asioによる非同期関数呼び出しと、非同期ノンブロッキングFuture Boost.Asioによる非同期関数呼び出しと、非同期ノンブロッキングFutureを含むブックマーク


C++ Advent Calendar 2012 に、参加させていただきました。
この記事は19日目になります
当初はboost asioのio_service周りの性能評価をネタに考えていたのですが、別のネタができたので、今回はこちらを紹介したいと思います

本記事は、イベント駆動アプリケーションの開発に役立つ、非同期(ノンブロッキング)関数呼び出しと、非同期ノンブロッキングFutureによる結果の受け取りについてです。

はじめに

高性能な分散システムサーバアプリケーションの開発をするには、マルチスレッドイベント駆動アーキテクチャ必須となります
Boost.Asioは、このようなアプリケーション開発に適したC++ライブラリです。

イベント駆動の大変なところ

イベント駆動アプリケーションの開発において障害になるのは、コールバック地獄です。

イベントハンドラで別の非同期関数を呼び出し、その結果をまた別のハンドラで受け取り、さらにそのハンドラ内で別の非同期関数を呼び出して・・・といったように
コールバックのコールバックのコールバック関数を書くことになります

void callbackC(std::shared_ptr<boost::asio::io_service> loop) {
 
}

void callbackB(std::shared_ptr<boost::asio::io_service> loop) {
  loop->post(std::bind(callbackC, loop));
}

void callbackA(std::shared_ptr<boost::asio::io_service> loop) {
  loop->post(std::bind(callbackB, loop));
}

この例は単純ですが、実際は必要引数の受け渡しや、エラー処理等が入ってきます。このように非同期関数の呼び出しごとに、処理の流れが飛んでしまうのでわかりづらくなってしまいます

そこで、このような非同期関数呼び出しと、非同期関数の結果受け取りを簡単に書けるようなラッパーを作ってみました。

ソースコード全体はこちら

非同期ノンブロッキングFuture

void callbackA(std::shared_ptr<boost::asio::io_service> loop) {
  // 非同期関数呼び出し
  Future<int> f = async(*loop, []() { return 100; });

  // 非同期関数の結果を受け取るコールバックをアタッチする
  f.attachCallback(
    [](Future<int> f) {
      try {
        cout << f.get() << endl;
      }
      catch(std::exception& e) {
        // エラー処理
      }
    }
  );
}

使い方は、std::futureと似ています
async()に、boost::asio::io_serviceと、呼び出したい関数を投げると、それがio_service::post()に投げられ非同期に実行されます
非同期関数の実行が終了したら、自動的にFutureクラスにアタッチしたコールバック関数が呼び出され、そこで結果を取得できます
非同期関数内で例外が発生した場合は、結果受け取り側でf.get()を呼び出した時点でその例外が再スローされるようになっています。これにより、エラー処理も簡単にかけると思います

ポイントは、イベントハンドラ内で呼び出した非同期関数の結果受け取りを、ブロッキングで待たない事です。
callbackAで呼び出している関数はすべて、すぐに制御を戻すノンブロッキング関数です。
イベントハンドラ内でブロッキング待機すると、その間そのスレッドは他のイベントを受け取れなくなるので、ブロッキング待機は使えないのです。

今後の発展

非同期ノンブロッキングFutureが本当に役立つのは、非同期なネットワークファイルI/O待受けだと思います
Boost_Asioをイベント駆動フレームワークとした、RPCライブラリがあればいいなと思っていて、その場合RPC呼び出しは以下のようにかけるようになると思います

void callbackA(std::shared_ptr<boost::asio::io_service> loop) {
  Future<int> f = RPC呼び出し(*loop, "rpc_func_a", arg1, arg2, ...);
  f.attachCallback(
    [](Future<int> f) {
      try {
        cout << f.get() << endl;
      }
      catch(std::exception& e) {
        // エラー処理
      }
    }
  );
}

おわりに

イベント駆動アプリケーションにおいて、非同期関数の結果をノンブロッキングに受け取るため、非同期ノンブロッキングFutureを紹介しました。
地味な話題でしたが、特にイベント駆動な分散システムを実装したことがある方には、やりたいことが分かっていただけると思います

yohhoyyohhoy 2012/12/20 10:59 興味深い内容でした。ご参考までに、次期C++標準への提案のなかに N3327 "A Standard Programmatic Interface for Asynchronous Operations" があり、同提案では「非同期Future」と似通った方向性で std::future の機能拡張を言及しています。
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3327.pdf

まだ粗削り感が否めないですが、ASIOとこの辺りの仕組みがうまいこと統合されると面白そうですね。

NIESNIES 2012/12/21 09:23 コメントありがとうございます。非同期Futureは非同期オペレーションにとってむしろプリミティブな要素だと思いますので、C++標準で使えるなら早く使ってみたいですね〜。
ちょうど今、複数の非同期Futureの待受をするwait_for_all(),wait_for_any()にあたる機能を作っていた所だったのですが、上記提案内に同様の機能の提案があったので、インタフェースを参考にしたいと思います。紹介ありがとうございました。

2011-07-20

GlusterFS性能評価 GlusterFS性能評価を含むブックマーク

TwitterのTLで話題になったので,最近測ったGlusterFS (version 3.2.1)の性能評価を公開してみたいと思います.

評価環境 評価環境を含むブックマーク

ノード数: 8 nodes
CPU: Intel(R) Xeon(TM) CPU 3.00GHz 2socket 1core + Hyper Threading
ネットワーク: 1Gbps
(iperf 839Mbps = 100MiB/sec)
ディスク性能:
/dev/sdb(2TB HDD) ext3
write: 103.70 MiB/sec
read: 124.32 MiB/sec

I/O throuput (dd)  I/O throuput (dd)を含むブックマーク

f:id:NIES:20110720195829p:image

write測定方法: dd if=/dev/zero of=file bs=1M count=4k conv=fdatasync
read測定方法: echo 1 > /proc/sys/vm/drop_caches後に dd if=file of=/dev/null bs=1M count=4k

サーバ1つずつbrickをvolumeに登録.8 bricksで1 volumeを構成.

考察

ファイルシステム操作スループット (mdtest)  ファイルシステム操作のスループット (mdtest)を含むブックマーク

f:id:NIES:20110720195830p:image

ファイルシステム操作スループット: mdtest(http://sourceforge.net/projects/mdtest/)を使用
8 clientからの並列{file|directory} create->stat->delete
クライアント1000個,合計8000個の{file|directory}をcreate->stat->delete

ditributed striped volumeについては,ファイル作成・削除に失敗する為,測定できなかった.原因は調査中です.

考察

wosugiwosugi 2011/07/21 11:45 久々な日記w元気〜?

AnaKutsuAnaKutsu 2011/07/23 05:47 前の記事との間隔がすごいねw

NIESNIES 2011/07/23 20:22 超久々でしたw元気です.今後は技術的な話題でアウトプットできるものがあれば,気が向いたらしていこうかと思っています.
mixi経由の友人からしたら,意味不明な内容になりそうですけど..

RSS feed meter for http://d.hatena.ne.jp/NIES/ なかのひと
ページビュー
329125