Boost Statechart vs. Meta State Machine

匿名 (未验证) 提交于 2019-12-03 02:44:02

问题:

Apparently boost contains two separate libraries for state machines: Statechart and Meta State Machine (MSM). The taglines give very similar descriptions:

  • Boost.Statechart - Arbitrarily complex finite state machines can be implemented in easily readable and maintainable C++ code.
  • Meta State Machine - A very high-performance library for expressive UML2 finite state machines.

Do you know what are the key differences and what are considerations in choosing between the two?

回答1:

As there seems to be much interest, please allow me to give my (obviously biased) opinion, which should therefore be taken with a grain of salt:

  • MSM is much faster
  • MSM requires no RTTI or anything virtual
  • MSM has a more complete UML2 support (for example internal transitions, UML-conform orthogonal regions)
  • MSM offers a descriptive language (actually several). For example, using the eUML front-end, a transition can be described as Source + Event [Guard] / Action == Target
  • MSM will make your compiler suffer for bigger state machines, so you will need a pretty recent compiler (g++ >= 4.x, VC >= 9)

You can make yourself a better opinion by looking for comments posted during the review of MSM. This subject was much discussed on the developer list.



回答2:

As Christophe has already mentioned, one of the key differences between the two libraries is runtime performance. While MSM probably offers the best you can get here, Statechart consciously trades memory and processor cycles towards better scalability.

With Boost.Statechart you can spread the layout (i.e. states, transitions) of your state machine over multiple translation units (cpp files) in ways you can't with MSM. This allows you to make the implementation of large FSMs more maintainable and get much faster compilation than with MSM.

Whether or not the performance overhead of Statechart compared to MSM will actually be significant for your application is often quite easy to answer when you ask yourself how many events your app will have to process per second.

Assuming a moderately complex FSM implemented with Boost.Statechart, here are a few ballpark numbers:

  • Most current PC hardware will easily cope with >100'000 events per second
  • Even very resource-constrained hardware will be able to process a few hundred events per second.

Regarding CPU load, if the number of events to process is much lower than these numbers, Boost.Statechart overhead compared to MSM will almost certainly not be noticeable. If the number is much higher, you're definitely better off with MSM.

More in-depth information on the performance/scalability tradeoffs can be found here: http://www.boost.org/doc/libs/1_45_0/libs/statechart/doc/performance.html



回答3:

While coding my own PPP implementation I used Statechart for three reasons: 1) Statechart is simpler and has clearer documentation; 2) I really dislike UML :)

Boost docs say MSM is at least 20 times faster, but compiles pretty slow for large FSM.



回答4:

Some time ago I began with Statechart and moved to MSM because it was easier to use in conjunction with asio from a single thread. I did not manage to mesh Statechart and its multithreading capabilities with my use of asio - it was likely some sort of newbie incomprehension of Statechart on my part. I found that MSM was easier to use as it did not address multithreading.



回答5:

In answer to Tim's late entry to the discussion (which also addresses one of the very early comments from Lev).

As one of those who argued for exit separation from destructors in statechart (argument based on a real use case, about interaction with the real world i.e. I/O) way back when it was submitted to Boost I agree there can be issues in putting exit logic in destructors. David Abrahams unsurprisingly made persuasive arguments regarding exception safety as well. For those reasons Statechart doesn't require you to put logic in destructors - but it allows you to - with the usual advice.

Logic that should only ever run as part of a transition out of a state (not destruction of the statechart object as a whole) can (and should if there is also resource cleanup to do) be separated into a separate exit() action.

For a "thin" state with no active state (resources), just entry/exit actions to perform, you can perform those actions in ctor and d'tor and make sure the constructor and destructor don't throw. There is no reason for them to - there is no state to perform RAII on - there is no evil in having the error handling in these places raise appropriate events. You may still need to consider whether you want exit actions that alter external state to run on state machine destruction though... and put them in exit action if you don't want them to occur in this case...

Statechart models activation as instantiation of an object, so if your constructor has real work/activation/instantiation to do and if it is able to fail such that the state cannot be entered Statechart supports that by giving you the ability to map an exception to an event. This is handled in a way that works up the state hierarchy looking for an outer state that handles the exception event, analogous to the way the stack would have unwound for a call stack based invocation model.

This is all well documented - I suggest you read the docs and try it. I suggest that you use destructors to clean up "software resources" and exit actions to perform "real-world exit actions".

It is worth noting note that exception propagation is a bit of a problem in all event driven environments, not just statecharts. It is best to reason about and include faults/errors in your statechart design and if and only if you can't handle them another way resort to exception mapping. At least that works for me - ymmmv....



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!