From: Steven Watanabe (steven_at_[hidden])
Date: 2007-01-31 14:02:24


AMDG

Andrey Semashev wrote:
> Hello,
>
> I've updated the Boost.FSM library in the Vault with the following
> changes:
> - Several threading issues pointed out by Steven Watanabe were fixed.
> - Some minor optimizations added to reduce the amount of generated
> code and possibly speed up compilation a little.
> - Exception classes are now exposed with default visibility on GCC 4.0
> and later under Linux. I'm not sure if other compilers/platforms
> need this and have support for similar feature.
> - A new example "BitMachine" added. It is quite similar to same-named
> example of Boost.Statechart and may be used as a performance test.
> - The Performance section of the docs updated with some test results.

First of all I think that the elapsed time is more useful than the
number of iterations per second. I know that one is just the
inverse of the other but the elapsed time has a linear correlation
to the amount of work being done.

Second, ~half the time taken for the benchmark is the
overhead of the test itself rather than the actual state machine.
Try this version.

#include <boost/mpl/for_each.hpp>
#include <boost/mpl/range_c.hpp>

//! Function Object version for MPL for_each
struct invoke_sm_func {
    typedef void result_type;
    invoke_sm_func(BitFSM_t& bfsm) : fsm(&bfsm) {
    }
    template<class Index>
    void operator()(Index) {
        invoke_sm<Index::value>(*fsm);
    }
    BitFSM_t* fsm;
};
//! Performance test implementation
void run_performance_test(BitFSM_t& fsm)
{
  //...

  // Execute performance loop
  for (register unsigned long i = 0, end = (unsigned
long)(NO_OF_PERFORMANCE_EVENTS / NO_OF_BITS); i < end; ++i)
  {
      boost::mpl::for_each<boost::mpl::range_c<int, 0, NO_OF_BITS>
>(invoke_sm_func(fsm));
  }
  //handle the remainder
  typedef boost::mpl::range_c<int, 0, (NO_OF_PERFORMANCE_EVENTS %
NO_OF_BITS)> tail;
  boost::mpl::for_each<tail>(invoke_sm_func(fsm));

  //...
}

Instead of using MPL vector/list you can create
your own MPL sequence.

struct StatesList_t {
    struct tag {};
    template<unsigned int N>
    struct iterator {
        typedef BitState<N> type;
        typedef iterator<N + 1> next;
    };
    typedef iterator<0> begin;
    typedef iterator<(1 << NO_OF_BITS)> end;
};

enum { NO_OF_STATES = (1 << NO_OF_BITS) };

In this case trying to reuse code actually generates
more work both for yourself and for the compiler.

In Christ,
Steven Watanabe