Jump to content

Action Engines... are we still using these?


Recommended Posts

1 hour ago, Neil Pate said:

The FGV (Action Engine actually) was used as the global storage of the temperatures and a mechanism for calculating the mean. The temperatures were needed all over the application (mainly for display purposes).

Please try and remember this was six years ago, and was done way before I had started to seriously use an sensible messaging framework. I am not suggesting this is how I would do it now-a-days.

I wasn't criticizing, just saying that with what I know now, today, I find it hard to even think about how you would use an FGV for this type of application. My thought process immediately goes a different direction.

 

Edit: Without interjecting myself too much into the other conversation, I don't really care if FGVs are by ref or not, they are often used for the same purpose as a DVR or single element queue but have a number of disadvantages for readability and reasoning about state vs the DVR. DVR's core disadvantage is that the syntax seems to have been designed by someone who really doesn't want people to use DVRs, while FGV syntax is much more developer-friendly.

 

Edited by smithd
  • Like 1
Link to comment
1 minute ago, smithd said:

I wasn't criticizing, just saying that with what I know now, today, I find it hard to even think about how you would use an FGV for this type of application. My thought process immediately goes a different direction.

Yes, this is exactly what I am thinking. That is why I put the question out there to other devs :-)

Link to comment
1 hour ago, ShaunR said:

I think the main point Smithd was making is that the current thinking about replacing AEs is to use DVRs but with messaging architectures, global storage is handled differently requiring neither. You have, however, restricted your options by insisting that you  don't want to use by-ref solutions (although I think you and a few others , maybe misunderstand what that exactly is since AEs are not by-ref) 

I suppose I must think about this differently to you. Wires are ByVal, everything else is not. FGVs/AEs are close enough to ByRef for me to lump them in the ByRef category.

Let me approach this from another angle: my actual goal. If I abort the entire project while a piece of code while it is running, and run that single VI (and of course whatever sub-VIs it calls etc) again, can I expect to get sensible values based purely on the current values of the input controls? This is the crux of what I am after. If I have to run many other "things" in the background just to get sensible results then, for me at least, this is undesirable.

If I want to test a particular portion of my code, say the algorithm that determines my calculated deformation (referring to my OP), then in 2016 I really want to code it in such a way that I can have a nice simple test harness and an entirely ByVal implementation (almost certainly a pure ByVal class implementation). Sure, in the bigger picture it may turn into ByRef somewhere else, but I am not too bothered by this.

Edited by Neil Pate
Link to comment
12 minutes ago, Neil Pate said:

If I abort the entire project while a piece of code while it is running, and run that single VI (and of course whatever sub-VIs it calls etc) again, can I expect to get sensible values based purely on the current values of the input controls?

Well. You wouldn't get that with an AE if you have the usual "First Run" check or have used the feedback node instead of shift registers internally. However. With a DVR, no (the ref goes invalid when idle). With a DB. Yes.

However. This is where I usually bring up the Suspend When Called :lol:

Link to comment
49 minutes ago, smithd said:

syntax seems to have been designed by someone who really doesn't want people to use DVRs

burn!

I also really dislike exposing the IPE anywhere on a top-level-ish block diagram, but it is painful to have the DVR as the input to a sub-VI...  and don't get me started about the error handling gymnastics required.

 

Edited by Neil Pate
Link to comment
21 minutes ago, ShaunR said:

Standard terms; not peculiar to LabVIEW.

Link title is "Passing Arguments by Value and by Reference"

Ah, so you’re meaning pass by reference, as applied to arguments to function calls (terminals in LabVIEW), and some of the things we are talking about are not passed as arguments.  

I’m meaning “act on by reference”, or “having a reference to something”, meaning I have the means of acting on something that others also can act on.  I don’t care if the reference is passed as an argument or is statically compiled in (like a Global or a subVI call).

 

Link to comment
54 minutes ago, drjdpowell said:

Link title is "Passing Arguments by Value and by Reference"

Ah, so you’re meaning pass by reference, as applied to arguments to function calls (terminals in LabVIEW), and some of the things we are talking about are not passed as arguments.  

I’m meaning “act on by reference”, or “having a reference to something”, meaning I have the means of acting on something that others also can act on.  I don’t care if the reference is passed as an argument or is statically compiled in (like a Global or a subVI call).

I think now I know where you are trying to get to, Indirection, of which "by reference" is an example. But the generalisation is inappropriate. AEs (and DVRs for that matter) are just memory accessors with some safeguards and maybe some logic. To conflate them with processes, subsystems and services where state rules supreme is a fallacy. DVRs and AEs are stateless accessors, nothing more. (That's not to say people don't try to stuff complex state-machines in AEs though :D )

Link to comment
1 hour ago, ShaunR said:

To conflate them with processes, subsystems and services where state rules supreme is a fallacy.

Eh? Where was that in the discussion?  I was comparing AE's, DVR-based by-ref objects, and "actors".  One can do complex or very simple things with any of them.  

Edited by drjdpowell
Link to comment
1 hour ago, drjdpowell said:

Eh? Where was that in the discussion?  I was comparing AE's, DVR-based by-ref objects, and "actors".  One can do complex or very simple things with any of them.  

Everything's an airplane with enough thrust, right?

Generalising to nebulous "actors" (which is just a hand-wave and means "insert your meaning here") and "objects" (which is another hand-wave meaning "describe something here") isn't the frame of the discussion. If that's the route, then I will generalise further to subsystems, services and processes since I don't have "actors" and "objects" - but that shouldn't matter, right? :P 

Just for reference were were at:

On 9/5/2016 at 0:14 PM, Neil Pate said:

Action Engines, aka LV2 style functional globals with a bit of embedded logic

and.....

On 9/7/2016 at 0:55 PM, Neil Pate said:

The alternative is the class private data is just a DVR. This is the convention adopted by G# and the other toolkit (GDS).

That's where we got sidetracked into the the LabVIEW implementation specifics of globals, wires and so on (where I lost you with my By Val/Ref.). Then you got me back with objects and actors, causing me to pass out through lack of oxygen :lol:  

 

Link to comment
2 hours ago, ShaunR said:

Generalising to nebulous "actors" (which is just a hand-wave and means "insert your meaning here")

Well, even at its most nebulous, “actors” interact by passing asynchronous messages, and are actively handling those messages.  “Message-handling loops”, basically.  That is significantly different than AE/DVRs, which passively wait to be synchronously called.  More specifically, “actors” should follow the Actor Model, and I should probably have used the more generic "Message-Handling Loop” as a thing to compare with Action Engines.

Link to comment
10 hours ago, drjdpowell said:

Well, even at its most nebulous, “actors” interact by passing asynchronous messages, and are actively handling those messages.  “Message-handling loops”, basically.  That is significantly different than AE/DVRs, which passively wait to be synchronously called.  More specifically, “actors” should follow the Actor Model, and I should probably have used the more generic "Message-Handling Loop” as a thing to compare with Action Engines.

That just takes us back to:

On 9/7/2016 at 11:56 AM, ShaunR said:

Actors and AEs aren't equivalent.

....and you seem to now agree. :)

Lets just keep it simple and talk about memory accessors.I don't think Neil wants to refactor all the code into several weeks worth of architectural redesign just to replace a very small component - rather a drop-in replacement for a standard (but possibly outdated) module type. (Pin for pin compatible,if possible).The problem is that for simplicity, efficacy and ease of debugging; there aren't many alternatives if you take DVRs off the table..

Edited by ShaunR
Link to comment

I am experimenting with a DVR based variant repository for my "global" data storage needs. Each actor in my system (everything is an actor) is able to reference this DVR and thus get at *any* data. Perhaps a bit dangerous, but as I said, this is an experiment. 

The application I am working is based on an older project, but is different enough, and needs enough work done to it that a complete architecture overhaul is sensible. 

So for now I have refactored my Action Engine to be a pure ByVal class that lives in my main controller, and I am just storing the result of the processing in the DVR.

Link to comment
On September 7, 2016 at 11:56 AM, ShaunR said:

Actors and AEs aren't equivalent.

Hey, let’s infinite-loop the conversation!  :)

On September 7, 2016 at 0:20 PM, drjdpowell said:

Actors, AEs and by-ref classes can all be used as wrappers around shared resources that serialize parallel access to them and protect critical sections of code.  They aren’t equivalent, but they have considerable overlap.   

I should clarify.  Message-handling loops, Action Engines, and by-ref classes can all be used to organize a complex application into subcomponents and control interactions between the subcomponents.  The means of interacting may be different, async messages versus sync subVI/method calls, but the purpose of these structures is the same.  Because they are different, but used for the same underlying purpose, I would recommend that a developer focus on one.  It reduces complexity if you standardize, and allows you to really get competent at the techniques you have chosen.  If asked, I would personally recommend using messages over any by-ref techniques, and also not using globally-accessibly things like standard AEs, but it is more important that one pick a technique and get good at it.

Link to comment
11 minutes ago, Neil Pate said:

I am experimenting with a DVR based variant repository for my "global" data storage needs. Each actor in my system (everything is an actor) is able to reference this DVR and thus get at *any* data. Perhaps a bit dangerous, but as I said, this is an experiment. 

What are you “global storage needs”?  How many writers are there of each data item?  

Link to comment

The way the architecture is designed there will only ever be a single writer of each data item, but these scattered across multiple actors (different hardware components and software interfaces).

The data in my application "runs slowly". Most new data comes in around about once per second so I do not really need to worry about extracting every last clock tick of performance out of my PC. Computers are crazy fast anyway these days, the bottleneck is certainly my skills.

Link to comment
1 hour ago, Neil Pate said:

The way the architecture is designed there will only ever be a single writer of each data item, but these scattered across multiple actors (different hardware components and software interfaces).

The data in my application "runs slowly". Most new data comes in around about once per second so I do not really need to worry about extracting every last clock tick of performance out of my PC. Computers are crazy fast anyway these days, the bottleneck is certainly my skills.

Single writer is good.  Why “global” then?   I generally have data flowing around by messages and locally stored by anyone who needs to store it.

The other issue is constantly polling a DVR for changes, versus receiving notification messages only when things change, but for “slow” apps that doesn’t matter much (but it affects your ability to reuse your solution in “fast” apps).  

Edited by drjdpowell
Link to comment
39 minutes ago, Neil Pate said:

I am experimenting with a DVR based variant repository for my "global" data storage needs. Each actor in my system (everything is an actor) is able to reference this DVR and thus get at *any* data. Perhaps a bit dangerous, but as I said, this is an experiment. 

The application I am working is based on an older project, but is different enough, and needs enough work done to it that a complete architecture overhaul is sensible. 

So for now I have refactored my Action Engine to be a pure ByVal class that lives in my main controller, and I am just storing the result of the processing in the DVR.

If you want to go all experimental......

There are "Tags" too which are global. IIRC I suppose they could be leveraged for this but I've never really looked at them

Another thing that I used to do before databases was to use an INI file to abuse the OS cache. Most people don't realise that reading and writing to an ini file directly is almost as fast as accessing memory once cached so there is no need to keep a lookup table in memory. (you can do the same with memapped files to share between executables too). This also has the side effect of giiving persistence  (great for resuming downloads that the user task-kills ;) ) 

 

Link to comment
5 minutes ago, ShaunR said:

There are "Tags" too which are global. IIRC I suppose they could be leveraged for this but I've never really looked at them

Oh yeah, there are quite a few “tag” libraries on NI.com.  Using one of those might be better than rolling your own.  I don’t use them because they wouldn’t give me anything I can’t do with messages, and they increase the amount of stuff I need to know (gotta know messaging, tags, and how tags interact with message timing).  

Link to comment
9 minutes ago, drjdpowell said:

Single writer is good.  Why “global” then?

Because of aggregation.

The goal is to average a number of values all being acquired asynchronously. There needs to be a way to snapshot the multiple values at an instance in time. If you use messaging then by the time you messaged each subsystem and got a response the values are not at the same instance in time. If you use events, then the event structure only operates sequentially so you have a similar problem. The AE makes this trivial. Other solution require all sorts of hoops.

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.