From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

DVR or data copy? How to deal with large data in AOP projects

Try this perhaps:

1) Receive a message that says "Something changed." Enqueue a new message to yourself that says, "Now gathering all changes". Record a state in your actor object that says "now gathering all changes".

2) Any further "something changed messages" go into an array that is a member of the actor object -- they either append or replace an existing element depending upon whether or not they're a unique source of updates.

3) When you finally get your own "Now gathering changes" message, process the messages in your array.

4) Go back to sleep until you get the next "something changed" message.

0 Kudos
Message 11 of 23
(1,912 Views)

jlokanis wrote:

Also, the UI processes always exist even if they are not being activly viewed.  So, the data might not have been written to an indicator until (and if) the user opens that view.

Why do you not launch the UI actors when viewed and close them when not needed?  This should be quite easy, given that you have a publish-subscribe system that remembers the last update.  Then you can scale to 100 UI components as only a few will be running (and registers for updates) at any one time.

0 Kudos
Message 12 of 23
(1,912 Views)

Why run the UI actors in the background?  Mainly because they use tree controls with lots of per cell color settings.  It is much better from a user perspective to update those trees in the background and then just show the UI when requested, than to try to draw the whole tree when they open the UI.  But, that being said, there are some UIs where I do exacly what you suggest.  It all depends on the needs of the use case I am trying to satisfy.

-John
------------------------
Certified LabVIEW Architect
0 Kudos
Message 13 of 23
(1,912 Views)

jlokanis wrote:

I have yet to stress it to a heavy load, but I suspect that I will hit another wall due to these data copies.  So, no, it is not acedemic.

If you haven't had observed the problem you're trying to solve, I'd call it academic.  I'm not saying you shouldn't be concerned or spend some time developing a contingency plan, just that the problem you're solving hasn't manifested itself yet.

jlokanis wrote:

In this case, being lossy on updates is ok.  Even desirable.  The Server might be very chatty, but the user only needs to see the UI updated once a second at best.

Seems to me the simplest solution is to create a Metronome that sends a "UpdateDisplay" message to each UI view once per second.  Have the UpdateDisplay message handler copy the most recent values that view is interested in out of the DVR and display them to the user.  Your average delay time between data update and UI update will be ~0.5 seconds.  Is that responsive enough?

0 Kudos
Message 14 of 23
(1,912 Views)

Random comments:

-- Since your "chatty" server is on the other side of a network connection, it might be best to limit the number of updates there rather than downstream on the UI client side.  TCP protocol already uses packet-number-limiting rules that accept delays of up to 200ms or so, so why not use similar logic to reduce the number of updates.

-- I don't know your project, but if I had "~20" state variables I would probably send updates about them individually (or in small close-knit groups) rather than as a single "state" object, and have other actors register only for the subset of information they need.  That way rapidly updating info needed by one UI doesn't trigger resending unchanged info to all actors.

-- Should your many UI components be full Actors?  You could have one or more "UI Manager" actors that receive the update messages and then updates UI components that are support loops using whatever technique is appropriate (such as waiting on a notifier, or an event structure, or just a simple subVI call).

Message 15 of 23
(1,912 Views)

Dave - I have been burned in the past by data copies I was not aware were happening.  I am trying to be proactive.  It is a PITA to re-write a bunch of messages and actors to change from DVR to by-value data.  I guess I would prefer to err on the side of caution and choose a design that will be the most robust, but at the same time I am trying to adhere to the AOP concepts because I fear unforeseen problems down the line with a DVR solution and a lack of clarity in the design.  Not that AOP is exactly clear in LV programming! 

Regarding filtering, I agree that the network channel could be the main problem going forward.  My current setup has both the server and client running on the same machine in separate projects for DEV purposes.  But the final version will be across a network.  I suspect I will see issues when I move to that setup that the current environment is masking.

I think the end solution will be a blend of DVR and by-value, where status data will use DVRs and one time data will remain by-value.

thanks again for the input.  It really helps to talk these things out instead of sitting in a cube staring at the screen all day, not knowing what direction to take.

-John
------------------------
Certified LabVIEW Architect
0 Kudos
Message 16 of 23
(1,912 Views)

jlokanis wrote:

Dave - I have been burned in the past by data copies I was not aware were happening.  I am trying to be proactive.

Like I said, there's nothing wrong with that.  I'm just trying to understand the situation as it exists right now.

jlokanis wrote:

I guess I would prefer to err on the side of caution and choose a design that will be the most robust...

Robust against what problems, specifically?  There is no design that is "most robust," only designs that are more (or less) suitable for your project's requirements. 

There are a few strategies available for addressing excessive data copies:

- Reduce the amount of data that is copied.

- Reduce the number of copies that are made.

- Reduce the frequency of the copy operation.

Each of these strategies lends itself to different solutions in code and requires different tradeoffs.  For example, earlier you said you send a copy of the entire data object to each view, even if it doesn't use all the data.  Obviously that represents wasted resources.  To fix that and reduce the amount of data that is copied, you can,

- Have the UI views create local copies from a DVR maintained by the client's data managing code.  (pull-model)

- Send each UI view only copies of the data they are going to use instead of the entire data object.  (push-model)

Some people prefer the by-reference model of sharing data and will choose the first solution.  I prefer sharing data by-value, so I favor the second solution.  Regardless of the solution you choose, at some point you start running into competing constraints and you have to decide (for example) if you'd rather deal with the potential problem of N views waiting for DVR access or the potential problem of creating data copies for N views.

To reduce the number of copies that are made you have to limit the number of views that are active at any one time.  That puts limitations on the UI that may or may not be acceptable in your project.

Reducing the frequency of copying data ultimately means throttling the messages that trigger a UI refresh.  You can choose to throttle them on the server side as James pointed out or on the client side before the copies are made.

Which strategy or combination of strategies should you choose?  I can't say... I don't have enough information to confidently recommend one solution over another.  It depends on your project's constraints.  But if you don't want to convert all your messages to DVRs then you don't have to.

0 Kudos
Message 17 of 23
(1,912 Views)

More random thoughts:

-- An additional advantage of sending individual messages for state information components, instead of a single "State"object, is that it reduces unneeded updates in the receiver.  "Item C changed" may only require a small amount of work, while "One or more of these 20 items has changed" may need a full redisplay.

-- Alternately, an advantage of sending the same "Everything" object to all listeners is that you could build all the messaging into a parent actor class, and have the UI actors inherit and just override an "Update" method.  Then you will have the ability to improve or completely change the communication details at a later date, as you will only have to modify one actor class.

0 Kudos
Message 18 of 23
(1,912 Views)

Well, I decided to try refactoring one portion of the code to use DVRs for shared data and I ran into something I should have remembered first:  You cannot replace the object a DVR stores with another copy of that same object.  In my case, I was creating a DVR of an object that represents data in a file.  I was storing that DVR reference in the state data of parent and child actors when I created them, so they would all have access.  I was also using the child actor to load that file, build the object and then store it so the parent would have access to the new data.  But due to this limitation with DVRs and Objects, I am not able to store the data in the existing DVR.

So, what are my options?  All the ones I can think of are bad (IMHO):

1. Change the DVR to store a variant and then store the object in that.  Drawback: Requires a cast every time I want to use it.  Cannot use property nodes to access the object elements.

2. Change the DVR to a SEQ.  Drawback: Cannot use property nodes to access the object elements.

3. Change the DVR to store another DVR of the object.  That way, I can replace the inner DVR ref altogether when I update it.  Drawbacks: Having to deref before I can use the inner DVR with property nodes.  Having the release the inner DVR when I replace it with a new one.

So, while I may stick with a DVR for the status object (since I do not replace this wholesale anywhere), I may revert to by-val for data that gets loaded from disk to fill out a object.

If you know a way around this, please share!

-John

-John
------------------------
Certified LabVIEW Architect
0 Kudos
Message 19 of 23
(1,912 Views)

John,

I have an AF project working across the network connecting a user interface to 2 cRIOs.  There can be different UI views of the data.  You can open up new windows that have the data presented in a different way (normal vs. engineering views for instance).  I have send my updates in several messages "update actuals", "update state", "change setpoint", "change state", etc.  I break with pure AF in my UIs.  I have a parent UI that will create a user event.  I then pass that to any child UI that I launch and I register for the event.  The parent receives the AF message over the network and then fires an event.  Any children that are open and registered for theevent will update their view.  My views don't store up historical data, but I can imagine ways to do that...

Casey

Casey Lamers


Phoenix, LLC


casey.lamers@phoenixwi.com


CLA, LabVIEW Champion


Check Out the Software Engineering Processes, Architecture, and Design track at NIWeek. 2018 I guarantee you will learn things you can use daily! I will be presenting!

0 Kudos
Message 20 of 23
(1,912 Views)