mirror of
https://github.com/boostorg/msm.git
synced 2026-01-23 05:42:21 +00:00
159 lines
6.1 KiB
Plaintext
159 lines
6.1 KiB
Plaintext
[[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_:
|
||
|
||
....
|
||
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.
|