c++ boost state-machines boost-statechart boost-msm

c++ - Boost Statechart vs. Meta State Machine



state-machines boost-statechart (5)

Al codificar mi propia implementación de PPP, utilicé Statechart por tres razones: 1) Statechart es más simple y tiene una documentación más clara; 2) Realmente no me gusta UML :)

Los documentos de Boost dicen que MSM es al menos 20 veces más rápido, pero compila bastante lento para FSM grandes.

Aparentemente boost contiene dos bibliotecas separadas para máquinas de estado: Statechart y Meta State Machine (MSM). Los eslóganes dan descripciones muy similares:

  • Boost.Statechart - Las máquinas de estados finitos arbitrariamente complejas se pueden implementar en código C ++ de fácil lectura y mantenimiento.
  • Meta State Machine: una biblioteca de muy alto rendimiento para expresivas máquinas de estados finitos UML2.

¿Sabes cuáles son las diferencias clave y cuáles son las consideraciones al elegir entre las dos?


Como Christophe ya ha mencionado, una de las diferencias clave entre las dos bibliotecas es el rendimiento en tiempo de ejecución. Si bien MSM probablemente ofrece lo mejor que puede obtener aquí, Statechart intercambia conscientemente ciclos de memoria y procesador para lograr una mejor escalabilidad.

Con Boost.Statechart puede distribuir el diseño (es decir, estados, transiciones) de su máquina de estado en varias unidades de traducción (archivos cpp) de forma que no puede hacerlo con MSM. Esto le permite hacer la implementación de grandes FSM más mantenibles y obtener una compilación mucho más rápida que con MSM.

Si la sobrecarga de rendimiento de Statechart en comparación con MSM será significativa o no para su aplicación, a menudo es bastante fácil de responder cuando se pregunta cuántos eventos tendrá que procesar su aplicación por segundo.

Suponiendo un FSM moderadamente complejo implementado con Boost.Statechart, aquí hay algunos números de estadio:

  • La mayoría del hardware de PC actual soportará fácilmente> 100''000 eventos por segundo
  • Incluso el hardware con recursos muy limitados podrá procesar unos cientos de eventos por segundo.

Con respecto a la carga de la CPU, si la cantidad de eventos que se van a procesar es mucho menor que estos números, la sobrecarga de Boost.Statechart en comparación con MSM casi nunca será perceptible. Si el número es mucho mayor, definitivamente estás mejor con MSM.

Se puede encontrar información más detallada sobre las compensaciones de rendimiento / escalabilidad aquí: http://www.boost.org/doc/libs/1_45_0/libs/statechart/doc/performance.html


Como parece que hay mucho interés, permítanme dar mi opinión (obviamente tendenciosa), que por lo tanto debería tomarse con un grano de sal:

  • MSM es mucho más rápido
  • MSM no requiere RTTI ni nada virtual
  • MSM tiene un soporte UML2 más completo (por ejemplo, transiciones internas, regiones ortogonales conformes a UML)
  • MSM ofrece un lenguaje descriptivo (en realidad varios). Por ejemplo, usando el front-end eUML, una transición puede describirse como Fuente + Evento [Guardia] / Acción == Target
  • MSM hará que su compilador sufra por máquinas de estado más grandes, por lo que necesitará un compilador bastante reciente (g ++> = 4.x, VC> = 9)

Puede hacerse una mejor opinión buscando comentarios publicados durante la revisión de MSM. Este tema fue muy discutido en la lista de desarrolladores.


En respuesta a la entrada tardía de Tim a la discusión (que también aborda uno de los primeros comentarios de Lev).

Como uno de los que abogó por la separación de salida de los destructores en Statechart (argumento basado en un caso de uso real, sobre la interacción con el mundo real, es decir, I / O) cuando se presentó a Boost, acepto que puede haber problemas para poner salida lógica en destructores. David Abrahams, como era de esperar, hizo argumentos persuasivos con respecto a la seguridad de excepciones también. Por esas razones, Statechart no requiere que ponga la lógica en destructores, pero le permite, con el consejo habitual.

La lógica que solo debe ejecutarse como parte de una transición fuera de un estado (no destrucción del objeto de diagrama de estado como un todo) puede (y debería si también hay una limpieza de recursos que hacer) separarse en una acción exit () separada.

Para un estado "delgado" sin estado activo (recursos), solo acciones de entrada / salida para realizar, puede realizar esas acciones en ctor and d''tor y asegurarse de que el constructor y el destructor no ejecuten. No hay ninguna razón para que lo hagan - no existe un estado para realizar RAII en adelante - no hay mal en que el manejo de errores en estos lugares genere eventos apropiados. Es posible que aún deba considerar si desea que las acciones de salida que alteran el estado externo se ejecuten en la destrucción de la máquina de estado ... y ponerlas en acción de cierre si no desea que ocurran en este caso ...

Statechart modela la activación como instanciación de un objeto, por lo tanto, si su constructor tiene trabajo real / activación / instanciación que hacer y si puede fallar tal que no se puede ingresar el estado, Statechart lo admite al darle la capacidad de asignar una excepción a un evento. Esto se maneja de una manera que funciona en la jerarquía de estado buscando un estado externo que maneje el evento de excepción, análoga a la forma en que la pila se habría desenrollado para un modelo de invocación basado en la pila de llamadas.

Todo esto está bien documentado: sugiero que lea los documentos y lo intente. Sugiero que use destructores para limpiar los "recursos de software" y las acciones de salida para realizar "acciones de salida del mundo real".

Vale la pena señalar que la propagación de excepciones es un problema en todos los entornos impulsados ​​por eventos, no solo en los gráficos de estado. Lo mejor es razonar e incluir fallas / errores en su diseño de diagrama de estado y si, y solo si no puede manejarlos, recurrir de otra manera al mapeo de excepciones. Al menos eso funciona para mí, mmmm ...


Hace algún tiempo comencé con Statechart y me mudé a MSM porque era más fácil de usar junto con asio desde un solo hilo. No logré conectar Statechart y sus capacidades de subprocesamiento múltiple con mi uso de asio; era probable que fuera una especie de incomprensión de novato de Statechart por mi parte. Descubrí que MSM era más fácil de usar ya que no abordaba el multihilo.