Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

Actor Overload!

AristosQueue wrote:

Ah. I thought you were asking about the runtime behavior... didn't realize you were talking about the edit time behavior.

Yes, there's pain at some point there. You don't see it at projects on the scale of 35 classes used for the evaporative cooler example. You do see it if you start heading up toward 100 classes. While I would love to see that pain fixed, the time delays in the editor as I work on projects of that scale are miniscule compared to the real loss of time to bugs I cannot track in larger programs without the good architectures.

Any chance you can come back to this thread?  Does the Compiler Optimizations setting in the Environment have anything to do with lvlib or LVOOP IDE performance?

CLA, CTA
0 Kudos
Message 31 of 44
(2,249 Views)

onnodb wrote:

Hopefully, this thread can serve as a signal that there's room for improvement in this area. Should this get priority from R&D? I'm sure you guys have plenty of juggling balls to keep in the air. In the meantime, *I* am definitely going to stick with the the AF

I think the best way for NI customers to voice their opinion is though the Idea Exchange.  Maybe someone could create a specific and detailed idea exchange entry on the performance of the IDE with large LVOOP applications.  If there are enough votes, it will definately put the issue on the radar for R&D.

CLA, CTA
0 Kudos
Message 32 of 44
(2,249 Views)

Discussion of slowdowns with large numbers of classes reminded me of this post by Paul_at_Lowell, where he describes using Abstract parent classes and Factories to avoid heavy interlinking between classes and improve things like load times and RT build times.

0 Kudos
Message 33 of 44
(2,249 Views)

LVB wrote:

I think you just summarized why people use a QMH/JKI State Machine: the ability to write (non-reusable) code quickly.

Could be.  I maintain hope people use it because they don't know any better techniques.  At least then we have some hope of them being willing to learn new methods.  On the other hand, if people use it because it's the fastest way to write code then getting the community to adopt better practices becomes more difficult.  I admit when it comes to getting something functional up quickly QSMs are hard to beat.  I also believe the time saved is quickly lost as the application grows.

LVB wrote:

I did attend Norm's presentation, and would like to review his slides and code when they become available.  What "state machine" would you suggest if not using the AF?  I am really interested in placing an easy to understand "state machine" inside the Actor Core as a building block towards actor oriented design.

I'm sure I have the example QSMs illustrating their problems around here somewhere.  I wrote it for a LVUG presentation last Oct. and gave it to Norm right after the summit in March.  I'll post it over on your Lava thread if I can dig it up.

LVB wrote:

What "state machine" would you suggest if not using the AF?  I am really interested in placing an easy to understand "state machine" inside the Actor Core as a building block towards actor oriented design.

First, I assume you mean a behavioral state machine (BSM), not a message handling loop or sequencer.  That means you can model the desired behavior using some combination of entry actions, do actions, exit actions, transition actions, and guard conditions on a state diagram.  (Note: A flowchart is not a state diagram.) 

Second, BSMs are orthogonal to the AF.  You can use them with or without the AF.  So this isn't just what I would suggest "if not using the AF."  It's what I use any time an application needs a BSM.

Essentially it is NI's state machine template extended to integrate into a message-based multi-threaded application.  It grew from my desire for a non-LVOOP implementation of the State Machine Pattern described in GoF.  I developed it because I was working with others who were not comfortable with objects.  This is the basic idea:

(Note: I used LapDog to create image this for my own convenience, but I have implemented it using standard string/variant messages.)

Example_VI_BD.png

The outer loop defines the boundaries of the entire state machine.  As long as code inside the loop is executing and the rules I mention below are followed, the state machine will be in a well-defined and knowable state with predictable responses to each message.  The case structure just inside the SM loop defines each of the possible states.  What goes inside each state varies depending on need, but I find message handling loops in each state are common.  Putting the message handling loop inside the state offers many advantages, one of which is it allows me to define custom behavior for each message depending on the state.  The number of states is significantly reduced compared to a typical QSM, making it easier to understand.  It is also remarkably easy to implement and identify entry and exit actions, as well as verify guard conditions.

There are many variations of this basic idea.  One of the things I really like about it is it not only scales well as functionality is added, but it scales well as the developer learns new OOP techniques. Once you understand the how it works it's pretty easy to customize it for a particular need or style without obfuscating its overall behavior--from simple stuff like using a string for states instead of an enum, all the way up to replacing the state and message handling case structures with objects.  Most of the exact details you see here aren't important, but some of the details that are important are not obvious.

Details I think are importan and inviolate:

1.  A reactive BSM must have a way to detect signals from the world outside of it.  I almost always use queues to transport signals in the form of messages, but I imagine notifiers, DVRs, globals, or other reference based data could also be used. 

2.  Nothing outside the state loop has the ability to directly change the state enum.  It is entirely under the control of the BSM.  (Contrast with QSMs, which allows other loops direct control over the state queue.)  If you're using a DVR for signal transport, the state enum is not part of the DVR data.

3.  A message handling loop must be able to appropriately handle any message at any time, without regard to the history of received messages or the expectation of future messages.  (This is applicable to any message handling loop, not just those in a BSM.  It is also applicable to actors, since they have a message handling loop.)

Details I think are important, but may have some flexibility:

4.  A BSM does not send messages to itself.  Signals bring information from external sources.  Sending a message to itself doesn't bring any new information and should not be necessary.  If I think I need self-messaging I go back to my state diagram and rework the design.  (Breaking this rule can easily lead to unknowingly breaking rule #3.)

5.  Continuous processes and message handlers are incompatible.  Don't try to simulate a continuous process by using a dequeue timeout or by having a message handler repeatedly execute by sending self-messages prior to exiting the message handling case.

I freely admit it's not all lollipops and gumdrops with this implementation.  I've found it works well for flat state machines, but Hierarchical State Machines are a different beast altogether, and I'm not satisfied with the HSM implementations I've attempted with this implementation pattern.  Also, if multiple states handle the same message identically it can lead to duplicate code.  Devs need to be aware of that so they can wrap the message handling code in a sub vi and call the sub vi from each state's message handler case.  Finally, this implementation is (imo) much more readable than state machines implemented with QSMs, but it not a substitute for documentation.  If the behavior required by the BSM is complex, the code implementing it will be complex.  Maintain an accurate state diagram.

There are a couple older threads on Lava (here and here) discussing this kind of state machine model, though they use an object-based implementation.

Message 34 of 44
(2,249 Views)

LVB wrote:

If there are enough votes...

That's the key right there.  As much as I applaude NI for creating the idea exchange, it's very, very, difficult for "advanced user" issues to fetch enough votes to get noticed.  Most people won't vote for it if it doesn't affect them, and relatively few users are building projects with enough classes to slow down the IDE.

Message 35 of 44
(2,249 Views)

drjdpowell wrote:

Discussion of slowdowns with large numbers of classes reminded me of this post by Paul_at_Lowell, where he describes using Abstract parent classes and Factories to avoid heavy interlinking between classes and improve things like load times and RT build times.

So he had to write lots more code in order to prevent being slowed down while writing code?

Message 36 of 44
(2,249 Views)

Daklu wrote:


As much as I applaude NI for creating the idea exchange, it's very, very, difficult for "advanced user" issues to fetch enough votes to get noticed.  Most people won't vote for it if it doesn't affect them, and relatively few users are building projects with enough classes to slow down the IDE.

Completely agreed. The Idea Exchange is a mechanism for NI to offload the labor of tracking and prioritizing complaints registered by their customers. That type of mechanism -- basically a bug reporting engine with a "vote" button -- works better for very tightly scoped complaints. When we take issue with the interactions of multiple features or products, or when we have a problem with the general "feel" of using the platform to accopmlish our goals, an open discussion forum is the best way to get that information through to the decision makers.

0 Kudos
Message 37 of 44
(2,249 Views)

AristosQueue wrote:

This will be my final reply on this thread.

That makes it easy to get in the last word!

I'm sorry if I pressed so hard on your pet project that I offended you. After taking some time off from the thread, I realize that I got too worked up and worded my criticism too strongly. My bad. I understand that fixes and changes take time. (I create software products for a living, too.) I didn't become agitated by the possibility of having to wait for LV 2013 or 2014 to get my pet issues addressed; I was set off when I perceived a nonchalant (and later personally defensive) response to our complaints about AF. Again, I'm sorry I started to attack.

I believe that criticism about usability is always valid with a daily-use product like LV, and it's NI's responsibility to listen when the users of a new feature resonate on specific points of feedback. Any decision to ignore complaints about edit-time performance when using AF will just result in continuing frustration for the end users, and we will naturally just stop using the feature. I don't want AF to end up the way the LV Statechart Module did. At least, not without some lighter-weight successor to replace it.

0 Kudos
Message 38 of 44
(2,249 Views)

LVB wrote:

Let's take the example of a simple boolean "state" set from a front panel control.

  • JKI State Machine
    • I can drop a Bundle By Name inside an event structure and wire data into the JKI State Machine shift register in about 5 seconds.
  • Actor
    • Creating a class method requires creation of a file on disk (10 seconds), an icon (30 seconds), and an associated message class (30 seconds)
    • Moving the message class on disk to the desired location (10 seconds), and then droping the message class into the event structure (10 seconds).

That would add up to 90 seconds compared to 5 seconds.

You are correct; if all you are doing is setting an attribute value, then AF would be heavy weight.  Messaging yourself to set a value can be kind of a drag.  In the more general case, where work is being done in the method call or case, I don't perceive much of a slowdown, because I'm spending most of my time coding the contents of the method call.

0 Kudos
Message 40 of 44
(2,249 Views)