web-dev-qa-db-ja.com

Boost Statechart vs. Meta State Machine

どうやらブーストには、ステートマシン用の2つの個別のライブラリが含まれています: Statechart および Meta State Machine (MSM)。キャッチフレーズは非常によく似た説明を提供します。

  • Boost.Statechart-任意の複雑な有限状態マシンを、読みやすく保守しやすいC++コードで実装できます。
  • メタ状態マシン-表現力豊かなUML2有限状態マシン用の非常に高性能なライブラリ。

重要な違いは何か、2つを選択する際の考慮事項は何ですか?

139
FireAphis

多くの関心があるように思われるので、私は(明らかに偏った)意見を述べさせてください。

  • MSMははるかに高速です
  • MSMはRTTIや仮想的なものを必要としません
  • MSMは、より完全なUML2サポートを備えています(たとえば、内部遷移、UML準拠の直交領域)。
  • MSMは記述言語(実際にはいくつか)を提供します。たとえば、eUMLフロントエンドを使用すると、遷移はソース+イベント[ガード] /アクション==ターゲットとして記述できます
  • MSMを使用すると、コンパイラがより大きなステートマシンに苦しむため、ごく最近のコンパイラが必要になります(g ++> = 4.x、VC> = 9)

MSMのレビュー中に投稿されたコメントを探すことで、より良い意見を得ることができます。このテーマは、開発者リストで詳しく議論されました。

113

クリストフがすでに述べたように、2つのライブラリの主な違いの1つは実行時のパフォーマンスです。 MSMはおそらくここで得られる最高のものを提供しますが、Statechartはメモリとプロセッササイクルを意図的に交換してスケーラビリティを向上させます。

Boost.Statechartを使用すると、ステートマシンのlayout(つまり、状態、遷移)を複数の変換単位(cppファイル)に広げることができます。 MSMでt。これにより、大規模なFSMの実装をより保守しやすくし、MSMよりもはるかに高速なコンパイルを実現できます。

MSMと比較したStatechartのパフォーマンスオーバーヘッドが実際にアプリケーションにとって重要であるかどうかは、アプリが1秒間に処理する必要のあるイベントの数を自問することで簡単に答えることができます。

Boost.Statechartで実装された適度に複雑なFSMを想定すると、ここにいくつかの球場番号があります。

  • 現在のほとんどのPCハードウェアは、1秒あたり100,000を超えるイベントに容易に対応します。
  • veryリソースに制約のあるハードウェアでも、毎秒数百のイベントを処理できます。

CPU負荷に関しては、処理するイベントの数がこれらの数よりはるかに少ない場合、MSMと比較してBoost.Statechartのオーバーヘッドはほとんど確実に目立たなくなります。数値がはるかに大きい場合、MSMを使用したほうが間違いなく優れています。

パフォーマンス/スケーラビリティのトレードオフに関する詳細な情報は、ここにあります: http://www.boost.org/doc/libs/1_45_0/libs/statechart/doc/performance.html

109
user49572

独自のPPP実装をコーディングしている間、私は次の3つの理由でステートチャートを使用しました。 2)私はUMLが本当に嫌いです:)

Boostのドキュメントによると、MSMは少なくとも20倍高速ですが、大規模なFSMではコンパイルがかなり遅くなります。

10
blaze

しばらく前に、Statechartから始めてMSMに移行しました。単一のスレッドからasioと組み合わせて使用​​する方が簡単だったからです。 asioを使用してステートチャートとそのマルチスレッド機能をメッシュ化することはできませんでした-おそらくステートチャートを初心者が理解していないかのようなものでした。 MSMはマルチスレッドに対応していないため、使いやすいことがわかりました。

4
Gordon M. Smith

議論へのティムの遅いエントリへの回答(これは、Levからの非常に初期のコメントの1つにも対応しています)。

ステートチャートのデストラクタからの出口の分離を主張した人の1人として(実際のユースケースに基づく議論、現実世界との相互作用、つまりI/O)Boostに提出されたとき、出口を置くことに問題があることに同意しますデストラクタのロジック。デビッド・アブラハムは、例外の安全性についても説得力のある議論を行った。これらの理由から、Statechartでは、デストラクタにロジックを配置する必要はありませんが、通常のアドバイスで可能です。

ステートからの遷移の一部としてのみ実行されるロジック(ステートチャートオブジェクト全体の破壊ではない)は、別のexit()アクションに分離できます(リソースクリーンアップも行う必要がある場合)。

アクティブな状態(リソース)がなく、実行するエントリ/終了アクションだけの「シン」状態の場合、それらのアクションをctorとd'torで実行し、コンストラクタとデストラクタがスローしないことを確認できます。彼らがRAIIを実行する状態がない理由はありません-これらの場所でエラー処理を行って適切なイベントを発生させることは悪ではありません。ただし、状態マシンの破壊時に外部状態を変更する終了アクションを実行するかどうかを検討する必要があります...この場合、それらを発生させたくない場合は、終了アクションに入れます...

ステートチャートはアクティベーションをオブジェクトのインスタンス化としてモデル化するため、コンストラクターに実際の作業/アクティベーション/インスタンス化があり、ステートに入らないように失敗できる場合、ステートチャートは例外をマップする機能を提供することでそれをサポートしますイベント。これは、呼び出しスタックベースの呼び出しモデルでスタックが巻き戻される方法と同様に、例外イベントを処理する外部状態を探して状態階層を処理する方法で処理されます。

これはすべてよく文書化されています-ドキュメントを読んで試してみることをお勧めします。デストラクタを使用して「ソフトウェアリソース」をクリーンアップし、「実際の終了アクション」を実行するアクションを終了することをお勧めします。

例外の伝播は、ステートチャートだけでなく、すべてのイベント駆動型環境で少し問題になることに注意してください。ステートチャートの設計にフォールト/エラーについて推論し、含めることをお勧めします。例外/マッピングを別の方法で処理できない場合に限ります。少なくともそれは私のために働く-ymmmv ....

2
da77a