Wzmocnij Statechart vs Meta State Machine


142

Najwyraźniej boost zawiera dwie oddzielne biblioteki dla maszyn stanowych: Statechart i Meta State Machine (MSM). Slogany podają bardzo podobne opisy:

  • Boost.Statechart - Dowolnie złożone maszyny o skończonych stanach można zaimplementować w czytelnym i łatwym w utrzymaniu kodzie C ++.
  • Meta State Machine - bardzo wydajna biblioteka dla ekspresyjnych maszyn skończonych UML2.

Czy wiesz, jakie są kluczowe różnice i jakie należy wziąć pod uwagę przy wyborze między nimi?


4
Hehe, kolejny przypadek bardzo interesujący, ale nikt nie zna odpowiedzi ... :)
j_random_hacker

8
: D To pytanie jest szczytem mojego doświadczenia z SO! Uzyskiwanie odpowiedzi od obu programistów ... czy może być lepiej ?! Podziękowania dla Christophe i Andreas.
FireAphis

Świetne pytanie i udało Ci się uzyskać odpowiedzi od dwóch konkurujących ze sobą programistów!
Offirmo

3
Statechart sprawia, że ​​umieszczasz funkcjonalność w konstruktorach i destruktorach. To anty-wzór, zwłaszcza w przypadku destruktorów.
Lew

2
W Statechart akcje wyjściowe można umieścić w osobnym module obsługi exit (), który jest wywoływany przed zniszczeniem. Myślę, że ten przepis łagodzi główny problem z anty-wzorcem, o którym wspomina Lev.
Tim Crews

Odpowiedzi:


116

Ponieważ wydaje się, że zainteresowanie jest duże, pozwolę sobie na wyrażenie mojej (oczywiście stronniczej) opinii, którą należy zatem przyjąć z przymrużeniem oka:

  • MSM jest znacznie szybszy
  • MSM nie wymaga RTTI ani niczego wirtualnego
  • MSM ma pełniejszą obsługę UML2 (na przykład przejścia wewnętrzne, regiony ortogonalne zgodne z UML)
  • MSM oferuje język opisowy (właściwie kilka). Na przykład, używając interfejsu eUML, przejście można opisać jako źródło + zdarzenie [ochrona] / akcja == cel
  • MSM sprawi, że Twój kompilator będzie cierpieć z powodu większych maszyn stanowych, więc będziesz potrzebować całkiem nowego kompilatora (g ++> = 4.x, VC> = 9)

Możesz wyrobić sobie lepszą opinię, szukając komentarzy zamieszczonych podczas recenzji MSM. Ten temat był szeroko omawiany na liście deweloperów.


2
Dziękuję Ci bardzo. Miło jest poznać opinię samego dewelopera! Teraz potrzebujemy tylko odpowiedzi Andreasa Hubera :)
FireAphis

16
Drobny wybór nitki: w trybie wydania użycie C ++ RTTI (dynamic_cast, typeid) jest całkowicie opcjonalne w przypadku Boost.Statechart.

111

Jak już wspomniał Christophe, jedną z kluczowych różnic między tymi dwiema bibliotekami jest wydajność w czasie wykonywania. Chociaż MSM prawdopodobnie oferuje najlepsze, co możesz tutaj uzyskać, Statechart świadomie zamienia cykle pamięci i procesora na lepszą skalowalność.

Dzięki Boost.Statechart możesz rozłożyć układ (tj. Stany, przejścia) swojego automatu stanów na wiele jednostek tłumaczeniowych (pliki cpp) w sposób, w jaki nie jest to możliwe w przypadku MSM. Pozwala to na łatwiejsze w utrzymaniu implementację dużych FSM i uzyskanie znacznie szybszej kompilacji niż w przypadku MSM.

Często łatwo odpowiedzieć na pytanie, czy narzut wydajności Statechart w porównaniu z MSM będzie istotny dla Twojej aplikacji, gdy zadasz sobie pytanie, ile zdarzeń będzie musiała przetworzyć Twoja aplikacja na sekundę.

Zakładając umiarkowanie złożony FSM zaimplementowany z Boost.Statechart, oto kilka liczb:

  • Większość obecnego sprzętu komputerowego z łatwością radzi sobie z> 100 000 zdarzeń na sekundę
  • Nawet sprzęt o bardzo ograniczonych zasobach będzie w stanie przetworzyć kilkaset zdarzeń na sekundę.

Jeśli chodzi o obciążenie procesora, jeśli liczba zdarzeń do przetworzenia jest znacznie niższa niż te liczby, obciążenie Boost.Statechart w porównaniu z MSM prawie na pewno nie będzie zauważalne. Jeśli liczba jest znacznie wyższa, zdecydowanie lepiej jest z MSM.

Więcej szczegółowych informacji na temat kompromisów między wydajnością a skalowalnością można znaleźć tutaj: http://www.boost.org/doc/libs/1_45_0/libs/statechart/doc/performance.html


9
Cześć Andreas, jeśli chodzi o rozpowszechnianie układu, nastąpiły pewne ulepszenia. Możesz teraz kompilować maszyny podrzędne na różnych rdzeniach. Nie jest doskonały, ale zauważalna poprawa. Zobacz svn.boost.org/svn/boost/trunk/libs/msm/doc/HTML/…
Christophe Henry

11

Podczas kodowania własnej implementacji PPP użyłem Statechart z trzech powodów: 1) Statechart jest prostszy i ma bardziej przejrzystą dokumentację; 2) Naprawdę nie lubię UML :)

Dokumentacja Boost mówi, że MSM jest co najmniej 20 razy szybszy, ale kompiluje się dość wolno dla dużych FSM.


7
Chociaż zgadzam się, że znaczna część UML to nowe szaty cesarzy, wykresy stanowe są jedyną rzeczą, która ma wartość w UML.
Jon Trauntvein

4
Zdecydowanie, ale wykresów stanu nauczyłem się z matematyki dyskretnej, a nie inżynierii oprogramowania. To pozostawia ślad :)
blaze

4

Jakiś czas temu zacząłem od Statechart i przeniosłem się na MSM, ponieważ łatwiej było go używać w połączeniu z asio z jednego wątku. Nie udało mi się połączyć Statechart i jego możliwości wielowątkowych przy użyciu asio - było to prawdopodobnie jakieś niezrozumienie Statechart przez początkujących. Odkryłem, że MSM jest łatwiejszy w użyciu, ponieważ nie dotyczy wielowątkowości.


1
Większość typów wykresów stanu również nie dotyczy wątków. Jeśli chodzi o wielowątkowość, powinieneś móc używać boost :: statechart :: state_machine tak samo, jak odpowiednika MSM. boost :: statechart :: asynchronous_state_machine i powiązane typy są ściśle opcjonalną częścią biblioteki statechart.

2

W odpowiedzi na późne wejście Tima do dyskusji (która dotyczy również jednego z bardzo wczesnych komentarzy Lwa).

Jako jeden z tych, którzy argumentowali za separacją wyjścia od destruktorów w statechart (argument oparty na prawdziwym przypadku użycia, o interakcji z rzeczywistym światem, tj. I / O) dawno temu, kiedy został przesłany do Boost, zgadzam się, że mogą wystąpić problemy z umieszczeniem wyjścia logika w destruktorach. Nie jest zaskakujące, że David Abrahams przedstawił przekonujące argumenty dotyczące również bezpieczeństwa wyjątków. Z tych powodów Statechart nie wymaga umieszczania logiki w destruktorach - ale pozwala - zgodnie ze zwykłymi radami.

Logika, która powinna zawsze działać tylko jako część przejścia ze stanu (a nie zniszczenia obiektu stanu stanu jako całości), może (i powinna, jeśli trzeba wykonać również czyszczenie zasobów), zostać rozdzielona na osobną akcję exit ().

W przypadku „cienkiego” stanu bez aktywnego stanu (zasobów), wystarczy wykonać akcje wejścia / wyjścia, możesz wykonać te akcje w ctor i d'tor i upewnić się, że konstruktor i destruktor nie rzucają. Nie ma powodu, aby - nie ma stanu, na którym mógłby wykonać RAII - nie ma nic złego w tym, że obsługa błędów w tych miejscach wywołuje odpowiednie zdarzenia. Nadal może być konieczne rozważenie, czy chcesz, aby akcje wyjścia, które zmieniają stan zewnętrzny, były uruchamiane po zniszczeniu automatu stanowego ... i umieść je w akcji wyjścia, jeśli nie chcesz, aby występowały w tym przypadku ...

Statechart modeluje aktywację jako instancję obiektu, więc jeśli twój konstruktor ma do wykonania rzeczywistą pracę / aktywację / instancję i jest w stanie zawieść, tak że stan nie może zostać wprowadzony, Statechart obsługuje to, dając ci możliwość zmapowania wyjątku do zdarzenie. Jest to obsługiwane w sposób, który działa w górę hierarchii stanów w poszukiwaniu stanu zewnętrznego, który obsługuje zdarzenie wyjątku, analogicznie do sposobu, w jaki stos zostałby rozwinięty w modelu wywołania opartym na stosie wywołań.

To wszystko jest dobrze udokumentowane - sugeruję przeczytanie dokumentacji i wypróbowanie tego. Sugeruję, abyś używał destruktorów do czyszczenia „zasobów oprogramowania” i akcji wyjścia w celu wykonania „akcji wyjścia w świecie rzeczywistym”.

Warto zauważyć, że propagacja wyjątków jest pewnym problemem we wszystkich środowiskach sterowanych zdarzeniami, a nie tylko w wykresach stanu. Najlepiej jest rozważać i uwzględniać błędy / błędy w projekcie swojego wykresu stanu i wtedy i tylko wtedy, gdy nie możesz sobie z nimi poradzić w inny sposób, skorzystaj z mapowania wyjątków. Przynajmniej to działa dla mnie - ymmmv ....


Dziękuję, widzę, że wszystkie moje obawy zostały wystarczająco omówione w części „Obsługa wyjątków” w samouczku Boost :: statechart. W takim przypadku myślę, że (mylący) komentarz Lwa można odnieść po prostu przez wskazanie sekcji „dwustopniowego wyjścia” tego samouczka. Rozważałbym usunięcie mojej odpowiedzi, z tym że Twoja własna odpowiedź dodaje cennych informacji do tego tematu.
Tim Crews
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.