Performance / Compilers

Tests were made on different PCs running Windows XP and Vista and compiled with VC9 SP1 or Ubuntu and compiled with g++ 4.2 and 4.3. For these tests, the same player state machine was written using Boost.Statechart, as a state machine with only simple states and as a state machine with a composite state. The same simple and composite state machines are implemented with MSM with a standard frontend (simple)(composite), the simple one also with functors and with eUML. As these simple machines need no terminate/interrupt states, no message queue and have no-throw guarantee on their actions, the MSM state machines are defined with minimum functionality. Test machine is a Q6600 2.4GHz, Vista 64.

Speed

VC9:

  • The simple test completes 90 times faster with MSM than with Boost.Statechart

  • The composite test completes 25 times faster with MSM

gcc 4.2.3 (Ubuntu 8.04 in VMWare, same PC):

  • The simple test completes 46 times faster with MSM

  • The composite test completes 19 times faster with MSM

Executable size

There are some worries that MSM generates huge code. Is it true? The 2 compilers I tested disagree with this claim. On VC9, the test state machines used in the performance section produce executables of 14kB (for simple and eUML) and 21kB (for the composite). This includes the test code and iostreams. By comparison, an empty executable with iostreams generated by VC9 has a size of 7kB. Boost.Statechart generates executables of 43kB and 54kB. As a bonus, eUML comes for ``free'' in terms of executable size. You even get a speed gain. With g++ 4.3, it strongly depends on the compiler options (much more than VC). A good size state machine with –O3 can generate an executable of 600kB, and with eUML you can get to 1.5MB. Trying with –Os –s I come down to 18kB and 30kB for the test state machines, while eUML will go down to 1MB (which is still big), so in this case eUML does not come for free.

Supported compilers

For a current status, have a look at the regression tests.

MSM was successfully tested with:

  • VC8 (partly), VC9, VC10

  • g++ 4.0.1 and higher

  • Intel 10.1 and higher

  • Clang 2.9

  • Green Hills Software MULTI for ARM v5.0.5 patch 4416 (Simple and Composite tutorials)

  • Partial support for IBM compiler

VC8 and to some lesser extent VC9 suffer from a bug. Enabling the option "Enable Minimal Rebuild" (/Gm) will cause much higher compile-time (up to three times with VC8!). This option being activated per default in Debug mode, this can be a big problem.

Limitations

  • Compilation times of state machines with > 80 transitions that are going to make you storm the CFO’s office and make sure you get a shiny octocore with 12GB RAM by next week, unless he’s interested in paying you watch the compiler agonize for hours…​ (Make sure you ask for dual 24" as well, it doesn’t hurt.)

  • eUML allows very long constructs but will also quickly increase your compile time on some compilers (VC9, VC10) with buggy decltype support (I suspect some at least quadratic algorithms there). Even g++ 4.4 shows some regression compared to 4.3 and will crash if the constructs become too big.

  • Need to overwrite the mpl::vector/list default-size-limit of 20 and fusion default vector size of 10 if more than 10 states found in a state machine

  • Limitation for submachines and entry actions requiring an event property.

Compilers corner

Compilers are sometimes full of surprises and such strange errors happened in the course of the development that I wanted to list the most fun for readers’ entertainment.

VC8:

template <class StateType>
typename ::boost::enable_if<
       typename ::boost::mpl::and_<
                typename ::boost::mpl::not_<
                    typename has_exit_pseudo_states<StateType>::type
                >::type,
                typename ::boost::mpl::not_<
                    typename is_pseudo_exit<StateType>::type
                >::type
       >::type,
       BaseState*>::type

I get the following error:

error C2770: invalid explicit template argument(s) for '`global namespace'::boost::enable_if<…​>::…​'

If I now remove the first ``::'' in ::boost::mpl, the compiler shuts up. So in this case, it is not possible to follow Boost’s guidelines.

VC9:

  • This one is my all times’ favorite. Do you know why the exit pseudo states are referenced in the transition table with a submachine::exit_pt''? Because exit'' will crash the compiler. ``Exit'' is not possible either because it will crash the compiler on one machine, but not on another (the compiler was installed from the same disk).

  • Sometimes, removing a policy crashes the compiler, so some versions are defining a dummy policy called WorkaroundVC9.

  • Typeof: While g++ and VC9 compile ``standard'' state machines in comparable times, Typeof (while in both ways natively supported) seems to behave in a quadratic complexity with VC9 and VC10.

  • eUML: in case of a compiler crash, changing the order of state definitions (first states without entry or exit) sometimes solves the problem.

_g 4.x_: Boring compiler, almost all is working almost as expected. Being not a language lawyer I am unsure about the following ``Typeof problem''. VC9 and g disagree on the question if you can derive from the BOOST_TYPEOF generated type without first defining a typedef. I will be thankful for an answer on this. I only found two ways to break the compiler:

  • Add more eUML constructs until something explodes (especially with g++-4.4)

  • The build_terminate function uses 2 mpl::push_back instead of mpl::insert_range because g++ would not accept insert_range.

You can test your compiler’s decltype implementation with the following stress test and reactivate the commented-out code until the compiler crashes.