Boost Statechart vs Meta State Machine

142

Apparemment, boost contient deux bibliothèques distinctes pour les machines à états: Statechart et Meta State Machine (MSM). Les slogans donnent des descriptions très similaires:

  • Boost.Statechart - Des machines à états finis arbitrairement complexes peuvent être implémentées dans un code C ++ facilement lisible et maintenable.
  • Meta State Machine - Une bibliothèque très performante pour les machines à états finis UML2 expressives.

Savez-vous quelles sont les principales différences et quelles sont les considérations à prendre en compte pour choisir entre les deux?

FeuAphis
la source
4
Hehe, un autre cas intéressant mais personne ne connaît la réponse ... :)
j_random_hacker
8
: D Cette question est le summum de mon expérience SO! Obtenir des réponses des deux développeurs ... ça peut aller mieux?! Un grand merci à Christophe et Andreas.
FireAphis
Excellente question et vous avez réussi à obtenir les réponses des deux développeurs concurrents!
Offirmo
3
Statechart vous permet de mettre des fonctionnalités dans les constructeurs et les destructeurs. C'est un anti-pattern, en particulier avec les destructeurs.
Lev
2
Dans Statechart, les actions de sortie peuvent être placées dans un gestionnaire exit () distinct qui est appelé avant la destruction. Je pense que cette disposition atténue le problème principal de l'anti-modèle mentionné par Lev.
Tim Crews

Réponses:

116

Comme il semble y avoir beaucoup d'intérêt, permettez-moi de donner mon avis (évidemment biaisé), qui doit donc être pris avec un grain de sel:

  • MSM est beaucoup plus rapide
  • MSM ne nécessite aucun RTTI ou quoi que ce soit de virtuel
  • MSM a un support UML2 plus complet (par exemple des transitions internes, des régions orthogonales conformes UML)
  • MSM propose un langage descriptif (en fait plusieurs). Par exemple, en utilisant l'interface eUML, une transition peut être décrite comme Source + Event [Guard] / Action == Target
  • MSM fera souffrir votre compilateur pour les machines à états plus grandes, vous aurez donc besoin d'un compilateur assez récent (g ++> = 4.x, VC> = 9)

Vous pouvez vous faire une meilleure opinion en recherchant les commentaires postés lors de l'examen de MSM. Ce sujet a été beaucoup discuté sur la liste des développeurs.

Christophe Henry
la source
2
Merci beaucoup. C'est un plaisir d'entendre l'opinion du développeur lui-même! Maintenant, nous n'avons besoin que de la réponse d'Andreas Huber :)
FireAphis
16
Minor nit-pick: En mode release, l'utilisation de C ++ RTTI (dynamic_cast, typeid) est strictement optionnelle avec Boost.Statechart.
111

Comme Christophe l'a déjà mentionné, l'une des principales différences entre les deux bibliothèques est la performance d'exécution. Alors que MSM offre probablement le meilleur que vous puissiez obtenir ici, Statechart échange consciemment les cycles de mémoire et de processeur pour une meilleure évolutivité.

Avec Boost.Statechart, vous pouvez répartir la mise en page (c'est-à-dire les états, les transitions) de votre machine d'état sur plusieurs unités de traduction (fichiers cpp) d'une manière que vous ne pouvez pas avec MSM. Cela vous permet de rendre l'implémentation de grands FSM plus facile à gérer et d'obtenir une compilation beaucoup plus rapide qu'avec MSM.

Il est souvent assez facile de savoir si la surcharge de performance de Statechart par rapport à MSM sera réellement significative pour votre application lorsque vous vous demandez combien d'événements votre application devra traiter par seconde.

En supposant un FSM modérément complexe implémenté avec Boost.Statechart, voici quelques chiffres approximatifs:

  • La plupart des matériels PC actuels peuvent facilement gérer plus de 100'000 événements par seconde
  • Même le matériel très limité en ressources sera capable de traiter quelques centaines d'événements par seconde.

En ce qui concerne la charge du processeur, si le nombre d'événements à traiter est bien inférieur à ces chiffres, la surcharge de Boost.Statechart par rapport à MSM ne sera presque certainement pas perceptible. Si le nombre est beaucoup plus élevé, vous êtes certainement mieux avec MSM.

Des informations plus détaillées sur les compromis performances / évolutivité sont disponibles ici: http://www.boost.org/doc/libs/1_45_0/libs/statechart/doc/performance.html


la source
9
Salut Andreas, à propos de la diffusion de la mise en page, il y a eu quelques améliorations. Vous pouvez maintenant compiler des sous-machines sur différents cœurs. Ce n'est pas parfait mais une amélioration notable. Voir svn.boost.org/svn/boost/trunk/libs/msm/doc/HTML/…
Christophe Henry
11

En codant ma propre implémentation PPP, j'ai utilisé Statechart pour trois raisons: 1) Statechart est plus simple et a une documentation plus claire; 2) Je n'aime vraiment pas UML :)

Les documents Boost indiquent que MSM est au moins 20 fois plus rapide, mais se compile assez lentement pour les gros FSM.

flamber
la source
7
Bien que je sois d'accord sur le fait qu'une grande partie d'UML est constituée des nouveaux vêtements des empereurs, les graphiques d'état sont la seule chose qui a réellement de la valeur dans UML.
Jon Trauntvein
4
Certainement, mais j'ai appris les statecharts à partir de mathématiques discrètes, pas de génie logiciel. Cela laisse une marque :)
blaze
4

Il y a quelque temps, j'ai commencé avec Statechart et je suis passé à MSM car il était plus facile à utiliser avec asio à partir d'un seul thread. Je n'ai pas réussi à mailler Statechart et ses capacités multithreading avec mon utilisation d'Asio - c'était probablement une sorte d'incompréhension débutant de Statechart de ma part. J'ai trouvé que MSM était plus facile à utiliser car il n'abordait pas le multithreading.

karma d'araignée
la source
1
La plupart des types d'états transitions n'abordent pas non plus le filetage. En ce qui concerne le multithreading, vous devriez être capable d'utiliser boost :: statechart :: state_machine comme l'équivalent MSM. boost :: statechart :: asynchronous_state_machine et les types associés sont une partie strictement facultative de la bibliothèque d'états.
2

En réponse à l'entrée tardive de Tim dans la discussion (qui répond également à l'un des tout premiers commentaires de Lev).

En tant que l'un de ceux qui ont plaidé pour la séparation de la sortie des destructeurs dans le statechart (argument basé sur un cas d'utilisation réel, à propos de l'interaction avec le monde réel, c'est-à-dire les E / S) il y a longtemps quand il a été soumis à Boost, je suis d'accord qu'il peut y avoir des problèmes pour mettre exit logique dans les destructeurs. Sans surprise, David Abrahams a également présenté des arguments convaincants concernant la sécurité des exceptions. Pour ces raisons, Statechart ne vous oblige pas à mettre de la logique dans les destructeurs - mais il vous le permet - avec les conseils habituels.

La logique qui ne devrait jamais s'exécuter que dans le cadre d'une transition hors d'un état (et non la destruction de l'objet d'états dans son ensemble) peut (et devrait s'il y a aussi un nettoyage de ressources à faire) être séparée en une action exit () distincte.

Pour un état "léger" sans état actif (ressources), juste des actions d'entrée / sortie à effectuer, vous pouvez effectuer ces actions dans ctor et d'tor et vous assurer que le constructeur et le destructeur ne lancent pas. Il n'y a aucune raison pour eux - il n'y a pas d'état sur lequel exécuter RAII - il n'y a aucun mal à ce que la gestion des erreurs dans ces endroits déclenche des événements appropriés. Vous devrez peut-être encore déterminer si vous voulez que les actions de sortie qui modifient l'état externe s'exécutent sur la destruction de la machine à états ... et les mettre en action de sortie si vous ne voulez pas qu'elles se produisent dans ce cas ...

Statechart modélise l'activation comme instanciation d'un objet, donc si votre constructeur a un vrai travail / activation / instanciation à faire et s'il est capable d'échouer de telle sorte que l'état ne puisse pas être entré Statechart prend en charge cela en vous donnant la possibilité de mapper une exception à un un événement. Ceci est géré d'une manière qui travaille la hiérarchie des états à la recherche d'un état externe qui gère l'événement d'exception, analogue à la façon dont la pile se serait déroulée pour un modèle d'appel basé sur une pile d'appels.

Tout cela est bien documenté - je vous suggère de lire la documentation et de l'essayer. Je vous suggère d'utiliser des destructeurs pour nettoyer les «ressources logicielles» et les actions de sortie pour effectuer des «actions de sortie du monde réel».

Il est à noter que la propagation d'exceptions est un peu un problème dans tous les environnements pilotés par les événements, pas seulement dans les statecharts. Il est préférable de raisonner et d'inclure les défauts / erreurs dans la conception de votre diagramme d'états et si et seulement si vous ne pouvez pas les gérer d'une autre manière, utilisez le mappage d'exceptions. Au moins cela fonctionne pour moi - ymmmv ....

da77a
la source
Merci, je constate que toutes mes préoccupations sont suffisamment abordées dans la partie "Gestion des exceptions" du tutoriel Boost :: statechart. Dans ce cas, je pense que le commentaire (trompeur) de Lev peut être adressé simplement en pointant vers la section "sortie en deux étapes" de ce tutoriel. J'envisagerais de supprimer ma réponse, sauf que votre propre réponse ajoute des informations précieuses à ce sujet.
Tim Crews