ステートチャート対メタステートマシンの強化


142

明らかにboostには、ステートマシン用の2つの個別のライブラリが含まれています。ステートチャートメタステートマシン(MSM)です。タグラインは非常によく似た説明を与えます:

  • Boost.Statechart-任意に複雑な有限状態マシンは、簡単に読み取りおよび保守可能なC ++コードで実装できます。
  • Meta State Machine-表現力豊かなUML2有限状態マシン用の非常に高性能なライブラリ。

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


4
Hehe、関心のある別のケースですが、誰も答えを知りません... :)
j_random_hacker

8
:Dこの質問は私のSO体験の頂点です!両方の開発者から回答を得る...それはもっと良くなるでしょうか?クリストフとアンドレアスに感謝します。
FireAphis 2010

すばらしい質問です。あなたはなんとかして2人の競合する開発者の答えを得ることができました。
Offirmo 2012年

3
ステートチャートを使用すると、機能をコンストラクタとデストラクタに組み込むことができます。これは、特にデストラクタでのアンチパターンです。
2014

2
ステートチャートでは、破棄アクションは破棄の前に呼び出される別のexit()ハンドラーに置くことができます。この規定は、レフが言及しているアンチパターンの主要な問題を軽減すると思います。
Tim Crews、2015年

回答:


116

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

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

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


2
どうもありがとうございました。開発者自身の意見を聞いて嬉しいです!これで、Andreas Huberの応答のみが必要になります:)
FireAphis 2010年

16
マイナーなnit-pick:リリースモードでは、C ++ RTTI(dynamic_cast、typeid)の使用は、Boost.Statechartでは厳密にオプションです。

111

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

Boost.Statechartを使用すると、MSMではできない方法で、ステートマシンのレイアウト(状態、遷移)を複数の変換単位(cppファイル)に分散できます。これにより、大きなFSMの実装を保守しやすくし、MSMを使用する場合よりもはるかに高速にコンパイルできます。

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

Boost.Statechartを使用して実装された適度に複雑なFSMを想定して、以下にいくつかの大まかな数値を示します。

  • 最新のPCハードウェアは、1秒あたり100,000を超えるイベントに簡単に対応します
  • でも、非常にリソースに制約のハードウェアは、毎秒数百回のイベントを処理することができるようになります。

CPU負荷に関しては、処理するイベントの数がこれらの数よりもはるかに少ない場合、MSMと比較したBoost.Statechartのオーバーヘッドはほとんど確実に目立ちません。数がはるかに多い場合は、MSMの方が間違いなく良いでしょう。

パフォーマンスとスケーラビリティのトレードオフの詳細については、http//www.boost.org/doc/libs/1_45_0/libs/statechart/doc/performance.htmlを参照してください。


9
こんにちはアンドレアス、レイアウトの広がりについて、いくつかの改善がありました。これで、さまざまなコアでサブマシンをコンパイルできます。完璧ではありませんが、顕著な改善です。svn.boost.org/svn/boost/trunk/libs/msm/doc/HTML/…を
Christophe Henry

11

独自のPPP実装をコーディングするときに、3つの理由でステートチャートを使用しました。1)ステートチャートの方が単純で、ドキュメントが明確です。2)私はUMLが本当に嫌いです:)

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


7
UMLの多くは皇帝の新しい服であることに同意しますが、ステートチャートはUMLで実際に価値のあるものの1つです。
Jon Trauntvein 2010年

4
確かに、私はステートチャートをソフトウェア工学ではなく離散数学から学んだ。これはマークを残します:)
ブレイズ

4

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


1
ほとんどのステートチャートタイプはスレッド化にも対応していません。マルチスレッドに関しては、MSMの対応物と同じようにboost :: statechart :: state_machineを使用できるはずです。boost :: statechart :: asynchronous_state_machineおよび関連するタイプは、ステートチャートライブラリの厳密にオプションの部分です。

2

Timのディスカッションへの遅れたエントリーへの回答(これは、Levからの非常に初期のコメントの1つにも対応しています)。

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

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

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

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

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

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


ありがとう、私の懸念はすべて、Boost :: statechartチュートリアルの「例外処理」の部分で十分に対処されているようです。その場合、Levの(誤解を招く)コメントは、そのチュートリアルの「2段階の出口」セクションをポイントするだけで対処できると思います。私自身の回答を削除することを検討します。ただし、あなた自身の回答がこのトピックに貴重な情報を追加する場合を除きます。
Tim Crews
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.