[[performance-compilers]]

= 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 xref:attachment$SCSimple.cpp[state machine with
only simple states] and as a xref:attachment$SCComposite.cpp[state machine
with a composite state]. The same simple and composite state machines
are implemented with MSM with a standard frontend
xref:attachment$MsmSimple.cpp[(simple)]xref:attachment$MsmComposite.cpp[(composite)],
the simple one also with xref:attachment$MsmSimpleFunctors.cpp[functors]
and with xref:attachment$EumlSimple.cpp[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]]

== 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]]

== 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]]

== Supported compilers

For a current status, have a look at the
http://www.boost.org/development/tests/trunk/developer/msm.html[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]]

== 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 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_:

[source,cpp]
----
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
xref:attachment$CompilerStressTestEuml.cpp[following stress test] and
reactivate the commented-out code until the compiler crashes.
