Boost logo

Boost Users :

Subject: Re: [Boost-users] finite state machine performance info
From: Franz Alt (f.alt_at_[hidden])
Date: 2009-11-27 03:37:44


I've already played with the Statechart library. I think it's a good
library but especially the fact that transitions take such a long time
isn't good in many situations like embedded systems for instance. Of
course Statechart has it's entitlement I think for you the new MSM
library (currently in review progress) is worth a look. State machines
build with MSM have very low overhead and are therefore very efficient.
I've taken a simple example to this mail. On my machine the state
machine with MSM is about 34 times faster than the one with Statechart.

Conoscenza Silente schrieb:
> Hi All
> Yesterday I started playing with Boost State Chart library
> implementing state machines for my applications.
> Each time I am moving into a new state I noticed that a new state is
> created; this means that the constructor of the
> boost::statechart::state class is called each time ( and the
> destructor for the state that I am leaving ).
>
> I would like to fasten up the whole process; let's say that I would
> like to avoid the creation/destruction of the class each time using
> object already allocated in memory that are deleted only at the exit
> of the application.
> Is this a good way in your opinion ?
>
> I saw that there is an allocator template argument but at the state
> where I am now I would lilke to not spend time in doing a new
> allocator for that: do you know if there already in place something
> that I can reuse for my purpose?
>
> Thanks CS
> _______________________________________________
> Boost-users mailing list
> Boost-users_at_[hidden]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users
>


#include <boost/statechart/simple_state.hpp>
#include <boost/statechart/state_machine.hpp>
#include <boost/statechart/event.hpp>
#include <boost/statechart/transition.hpp>
#include <boost/timer.hpp>
#include <boost/progress.hpp>
#include <boost/pool/pool_alloc.hpp>
#include <boost/msm/back/state_machine.hpp>
#include <boost/msm/front/state_machine_def.hpp>

using namespace boost::statechart;

namespace test_sc
{
    struct state_1;
    struct state_2;
    struct state_3;
    struct state_4;
    struct main_machine :
    state_machine<
    main_machine,
    state_1

    // without allocator I have 5.6 seconds (used also in events)

    //,boost::pool_allocator< main_machine > // with this
    // allocator I go to 10 sec used also in events

    //,boost::fast_pool_allocator< main_machine > // with this
    //allocator I go to 8.7 sec

> {};

struct event_1_2 : event< event_1_2
    //, boost::fast_pool_allocator< event_1_2 >
>{};
struct event_2_3 : event< event_2_3
    //, boost::fast_pool_allocator< event_2_3 >
>{};
struct event_3_4 : event< event_3_4
    //, boost::fast_pool_allocator< event_3_4 >
>{};
struct event_4_1 : event< event_4_1
    //, boost::fast_pool_allocator< event_4_1 >
>{};

struct state_1
    : simple_state< state_1, main_machine >
{
    typedef transition< event_1_2, state_2 > reactions;
};

struct state_2
    : simple_state< state_2, main_machine >
{
    typedef transition< event_2_3, state_3 > reactions;
};

struct state_3
    : simple_state< state_3, main_machine >
{
    //typedef transition< event_3_4, state_4 > arc; // it doesn't work
    typedef transition< event_3_4, state_4 > reactions;

    //state_3(){std::cout<<"3";}
    //~state_3(){std::cout<<"~3";}
};

struct state_4
    : simple_state< state_4, main_machine >
{
    typedef transition< event_4_1, state_1 > reactions;
};
}

namespace msm = boost::msm;
namespace mpl = boost::mpl;

namespace test_msm // Concrete FSM implementation
{
    struct event_1_2 {};
    struct event_2_3 {};
    struct event_3_4 {};
    struct event_4_1 {};
    // Concrete FSM implementation
    struct main_machine_ : public msm::front::state_machine_def<main_machine_>
    {
        // no need for exception handling or message queue
        typedef int no_exception_thrown;
        typedef int no_message_queue;
        // The list of FSM states
        struct state_1 : public msm::front::state<>
        {
            // optional entry/exit methods
            //template <class Event,class FSM>
            //void on_entry(Event const&,FSM& ) {std::cout << "entering: state_1" << std::endl;}
            //template <class Event,class FSM>
            //void on_exit(Event const&,FSM& ) {std::cout << "leaving: state_1" << std::endl;}
        };
        struct state_2 : public msm::front::state<>
        {
            // optional entry/exit methods
            //template <class Event,class FSM>
            //void on_entry(Event const&,FSM& ) {std::cout << "entering: state_2" << std::endl;}
            //template <class Event,class FSM>
            //void on_exit(Event const&,FSM& ) {std::cout << "leaving: state_2" << std::endl;}
        };
        struct state_3 : public msm::front::state<>
        {
            // optional entry/exit methods
            //template <class Event,class FSM>
            //void on_entry(Event const&,FSM& ) {std::cout << "entering: state_3" << std::endl;}
            //template <class Event,class FSM>
            //void on_exit(Event const&,FSM& ) {std::cout << "leaving: state_3" << std::endl;}
        };
        struct state_4 : public msm::front::state<>
        {
            // optional entry/exit methods
            //template <class Event,class FSM>
            //void on_entry(Event const&,FSM& ) {std::cout << "entering: state_4" << std::endl;}
            //template <class Event,class FSM>
            //void on_exit(Event const&,FSM& ) {std::cout << "leaving: state_4" << std::endl;}
        };
        // the initial state of the player SM. Must be defined
        typedef state_1 initial_state;

        struct transition_table : mpl::vector<
        // Start Event Next Action Guard
        // +---------+-------------+---------+---------------------+----------------------+
         _row < state_1 , event_1_2 , state_2 >,
         _row < state_2 , event_2_3 , state_3 >,
         _row < state_3 , event_3_4 , state_4 >,
         _row < state_4 , event_4_1 , state_1 >
        // +---------+-------------+---------+---------------------+----------------------+
> {};
    };
    typedef msm::back::state_machine<main_machine_> main_machine;

}
void main(){
    test_sc::main_machine fsm;
    fsm.initiate();
    {
        boost::progress_timer t; // count the time elapsed
        // before distruction: not very precise
        // for expected big differences

        for( int i = 0; i < 1000000; i ++ ){

            fsm.process_event( test_sc::event_1_2() );
            fsm.process_event( test_sc::event_2_3() );
            fsm.process_event( test_sc::event_3_4() );
            fsm.process_event( test_sc::event_4_1() );
        }
    }
    test_msm::main_machine fsm2;
    fsm2.start();
    {
        boost::progress_timer t; // count the time elapsed
        // before distruction: not very precise
        // for expected big differences

        for( int i = 0; i < 1000000; i ++ ){

            fsm2.process_event( test_msm::event_1_2() );
            fsm2.process_event( test_msm::event_2_3() );
            fsm2.process_event( test_msm::event_3_4() );
            fsm2.process_event( test_msm::event_4_1() );
        }
    }
}


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net