Boost Statechart vs. Meta State Machine

142

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

  • Boost.Statechart: se pueden implementar máquinas de estado finito arbitrariamente complejas en código C ++ fácil de leer y mantener.
  • Meta State Machine: una biblioteca de muy alto rendimiento para máquinas de estados finitos UML2 expresivos.

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

FireAphis
fuente
44
Jeje, otro caso de mucho interés pero nadie sabe la respuesta ... :)
j_random_hacker
8
: D ¡Esta pregunta es el pináculo de mi experiencia SO! Obteniendo respuestas de ambos desarrolladores ... ¿puede mejorar? Muchas gracias a Christophe y Andreas.
FireAphis
¡Excelente pregunta y lograste obtener las respuestas de los dos desarrolladores competidores!
Offirmo
3
Statechart te hace poner funcionalidad en constructores y destructores. Eso es un antipatrón, especialmente con destructores.
Lev
2
En Statechart, las acciones de salida se pueden colocar en un controlador de salida () separado que se llama antes de la destrucción. Creo que esta disposición mitiga el problema principal con el antipatrón que menciona Lev.
Tim Crews

Respuestas:

116

Como parece haber mucho interés, permítame dar mi opinión (obviamente sesgada), que por lo tanto debe 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 con UML)
  • MSM ofrece un lenguaje descriptivo (en realidad varios). Por ejemplo, usando el front-end eUML, una transición se puede describir como Source + Event [Guard] / Action == 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.

Christophe Henry
fuente
2
Muchas gracias. ¡Es una delicia escuchar la opinión del propio desarrollador! Ahora solo necesitamos la respuesta de Andreas Huber :)
FireAphis
16
Min-nit-pick: en el modo de lanzamiento, el uso de C ++ RTTI (dynamic_cast, typeid) es estrictamente opcional con Boost.Statechart.
111

Como ya ha mencionado Christophe, 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 los ciclos de memoria y procesador hacia 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 formas que no puede hacerlo con MSM. Esto le permite hacer que la implementación de FSM grandes sea más fácil de mantener 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á realmente significativa 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 muy hardware con recursos limitados será capaz de procesar unos pocos cientos de eventos por segundo.

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

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


fuente
9
Hola Andreas, sobre la difusión del diseño, ha habido algunas mejoras. Ahora puede compilar submáquinas en diferentes núcleos. No es perfecto sino una mejora notable. Ver svn.boost.org/svn/boost/trunk/libs/msm/doc/HTML/…
Christophe Henry el
11

Mientras codificaba 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 se compila bastante lento para FSM grandes.

resplandor
fuente
77
Si bien estoy de acuerdo en que gran parte de UML es la ropa nueva del emperador, los gráficos de estado son lo único que realmente tiene valor en UML.
Jon Trauntvein
44
Definitivamente, pero aprendí gráficos de estado de matemáticas discretas, no de ingeniería de software. Esto deja una marca :)
blaze
4

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é mezclar Statechart y sus capacidades de subprocesamiento múltiple con mi uso de asio; probablemente fue una especie de incomprensión novata de Statechart de mi parte. Descubrí que MSM era más fácil de usar ya que no abordaba el subprocesamiento múltiple.

karma araña
fuente
1
La mayoría de los tipos de gráficos de estado tampoco abordan el subproceso. Con respecto al subprocesamiento múltiple, debería poder usar boost :: statechart :: state_machine al igual que la contraparte de MSM. boost :: statechart :: asynchronous_state_machine y los tipos asociados son una parte estrictamente opcional de la biblioteca de statechart.
2

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 la salida de los destructores en el diagrama de estado (argumento basado en un caso de uso real, sobre la interacción con el mundo real, es decir, E / S) cuando se envió a Boost, estoy de acuerdo en que puede haber problemas al poner la salida lógica en destructores. Como era de esperar, David Abrahams también hizo argumentos persuasivos con respecto a la seguridad de excepción. Por esas razones, Statechart no requiere que coloque la lógica en los destructores, pero se lo permite, con los consejos habituales.

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

Para un estado "delgado" sin estado activo (recursos), solo acciones de entrada / salida para realizar, puede realizar esas acciones en ctor y d'tor y asegurarse de que el constructor y el destructor no se ejecuten. No hay ninguna razón para que lo hagan, no hay un estado en el que realizar RAII, no hay nada malo en que el manejo de errores en estos lugares genere eventos apropiados. Sin embargo, es posible que 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 salida si no desea que ocurran en este caso ...

Statechart modela la activación como instanciación de un objeto, por lo que si su constructor tiene trabajo real / activación / instanciación que hacer y si puede fallar de tal manera que no se pueda ingresar el estado, Statechart lo respalda 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, de forma 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. Te sugiero que leas los documentos y lo pruebes. Le sugiero que use destructores para limpiar "recursos de software" y 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 controlados por eventos, no solo en los gráficos de estado. Es mejor razonar e incluir fallas / errores en el diseño de su diagrama de estado y si y solo si no puede manejarlos de otra manera recurra al mapeo de excepciones. Al menos eso funciona para mí, ymmmv ...

da77a
fuente
Gracias, veo que todas mis preocupaciones se abordan suficientemente en la parte "Manejo de excepciones" del tutorial Boost :: statechart. En ese caso, creo que el comentario de Lev (engañoso) puede abordarse simplemente señalando la sección "salida de dos etapas" de ese tutorial. Consideraría eliminar mi respuesta, excepto que su propia respuesta agrega información valiosa a este tema.
Tim Crews