boost-ext / sml

C++14 State Machine library
https://boost-ext.github.io/sml
Boost Software License 1.0
1.16k stars 178 forks source link

Unexpectedly high sizeof(sm) #458

Open ukreator opened 3 years ago

ukreator commented 3 years ago

Expected Behavior

Ideally, sizeof(sm) of the state machine below to be 9 bytes (this pointer for lambda and one byte to store the current state).

Actual Behavior

sizeof(sm) is 80 bytes

Steps to Reproduce the Problem

Compile and run

  struct c {
    auto operator()() noexcept {
      using namespace sml;
      return make_transition_table(
         *"idle"_s + "ev1"_e [ &c::guard ] / &c::action = X,
          "idle"_s + "ev2"_e / [this]{} = X
      );
    }

    auto guard() const -> bool { return true; }
    void action() { action_ = true; }
    bool action_{};
  };

  std::cout << sizeof(sml::sm<c>{}) << std::endl;

Specifications

In the example above it looks like SML saves this and some additional info per member function and 8 bytes per lambda capturing this for every mention of those lambdas/function members.

Are there any tips and tricks to reduce the size that is needed by a state machine when it has non-trivial actions/conditions? Especially when conditions/actions need to capture this.

For the context, I have hundreds/thousands of state machine instances saved in flat hash maps so it gets expensive when re-hashing happens (it has to copy hundreds of bytes per node).

dingari commented 3 years ago

Would be very interested in getting some insight from the library maintainers as well.

In our project we have a rather large/complex FSM with a lot of lambdas using auto-capture. The size of the FSM instance in our case accounts to about 1KB in v1.1.3 but grows upwards of 33KB in v1.1.4.

Our FSM is just statically allocated and never moves, but being in an embedded context, keeping the FSM size as low as possible is absolutely crucial.

anb0s commented 3 years ago

I had the same problem with GCC 10.x see #351 have to check if still an issue...