Jump to content

LV2009 Data Value References should be used SPARINGLY


Recommended Posts

This is my attempt to depress, suppress and restrain the excitement running through the community regarding Data Value References in LabVIEW 2009.

Yes, they are cool.

Yes, they are powerful.

Yes, they solve problems real programming problems.

Yes, you should occasionally use them.

No, they are not a silver bullet.

But please, for the love of LabVIEW, don't go overboard. They are references. They are not dataflow. You can kill an app's performance by needlessly using references of any kind -- queues, file i/o, GOOP, and, yes, DVRs. Think before you use the references. Ask yourself if you need the references. Even if you think you do, try to not use them first. I have seen more than one user app where a knee-jerk reaction to wrap *everything* in a single-element queue and passing references around kills performance.

We have developed DVRs to be as parallel-safe as possible, but there are still hangs that can occur if you use them in some ways -- Jim Kring found one just last week, and thought he was looking at a bug in LabVIEW, but it wasn't. When you use references, you open up a whole new world of race conditions, recursive deadlock, and on and on.

Let the LabVIEW community celebrate the new Data Value References. But, please, celebrate calmly.

Link to comment

" Jim Kring found one just last week, and thought he was looking at a bug in LabVIEW, but it wasn't. When you use references, you open up a whole new world of race conditions, recursive deadlock, and on and on. "

Has this been posted somewhere so that we can see what happened? This is an important tip because I'm sure some would understand DVR as meaning "unlimited by-ref" had come to LVOOP.

Link to comment
Has this been posted somewhere so that we can see what happened? This is an important tip because I'm sure some would understand DVR as meaning "unlimited by-ref" had come to LVOOP.
Unlimited by-ref has come. And that's the problem. :-) His program was not a case of LV having a bug, but rather he just coded something where Diagram Alpha was using a reference and Diagram Beta tried to acquire that reference, and was waiting, and, meanwhile, Alpha was waiting on Beta before Alpha would release the reference. And his program sat and waited on itself.
Link to comment

Unlimited by-ref has come. And that's the problem. :-) His program was not a case of LV having a bug, but rather he just coded something where Diagram Alpha was using a reference and Diagram Beta tried to acquire that reference, and was waiting, and, meanwhile, Alpha was waiting on Beta before Alpha would release the reference. And his program sat and waited on itself.

...and then it suddenly stood up and said: "I'm not waiting for this bloody reference, I'm going back to 8.6"

Edited by vugie
Link to comment

...and then it suddenly stood up and said: "I'm not waiting for this bloody reference, I'm going back to 8.6"

Kind of a "retro-occurrence"....with an attitude!

AQ, am I hearing that byval has an inherent "advantage" in that it enforces dataflow and precludes (more or less) race conditions whereas the byref option ALLOWS for race conditions, unless otherwise handled in the architecture?

Link to comment

...whereas the byref option ALLOWS for race conditions, unless otherwise handled in the architecture?

It doesn't allow for classic race conditions (two places changing the same piece of data) because you HAVE to lock the data every time you want to access it (even if it's just for reading).

What it does allow are deadlocks, which is what AQ was refering to. If you want a simple example, think of this psuedocode:

A{ Lock (Data) B() Unlock (Data)}B{ Lock (Data) ... Unlock (Data)}

A and B operate on the same data, so they each begin by requesting a lock. When you call A it request a lock, gets the lock and calls B.

B then requests a lock, but doesn't get it because A already locked the data. Now B has to wait until A releases the lock and A has to wait until B finishes execution. That's deadlock.

You know for sure you're going to run into this problem if you have a reference crossing the boundary of an IPE structure where it's been used. If you're using a reference in a structure, DON'T let that reference cross the boundary of the structure.

Presumably the issue Jim ran into is more complicated, but the concept is basically the same - when you have a lock, you can lock yourself out in any number of ways.

  • Like 1
Link to comment

Hi AQ,

I do not mean to take this thread of topic but your comment "You can kill an app's performance by needlessly using references of any kind" made me stop and worry exactly what you meant and in what context :( .

I have started to rewrite some very old systems here using a mixture of the JKI State Machine and a parallel user event loop. Until now I was feeling quite pleased with myself, I felt it look good code, was following a good pattern, however now I am not so sure.

On my top-level front panel I have quite a few controls and indicator a number of which need updating from lower in the code (as we all often do).

A lot of my style to tidy things up was to cluster common control / indicators together, I would then create references to these clusters and other controls / indicators on the front panel. All these references would then themselves be clustered together and, in the JKI state machine world these clusters of references would then going to shirft registar so they could be accessed everywhere by just pulling them out of the cluster as and where required.

Your comments abvoew make me thing this may be a very bad way of doing things.

Could you please expand this maybe in a new thread

cheers

Dannyt

Link to comment

I believe the main issue AQ was considering was that a reference always points to a shared resource.

Question - When you have a shared resource (e.g. a clerk at the post office), what do you get when you have multiple users who want that resource?

Answer - A line.

Suppose you just want to buy three stamps, but the person at the top of the line is sending Christmas presents to his 47 cousins. What happens? You have to wait 40 minutes. The same thing would happen in your program - the more bottlenecks you have, the more likely you are to have places in your code which are waiting on other places.

In the specific case of references to controls I believe you can incur three additional penalties -

  1. If you're writing the value to the control from multiple places you most likely have race conditions.
  2. I'm pretty sure that every interaction (at least a write one) with a control's property forces that control to be drawn on-screen, unless the defer updates property is set to T.
  3. If you're reading the control's value, you have a memory allocation for the wire, which takes time. DVRs were specifically designed to also not have this problem.

All that said, it doesn't mean your architecture is invalid. Passing references to controls to subVIs in order to control or query the UI is certainly valid and would not necessarily slow your program to a halt. If you're trying to do these calls a million times a second while measuring a 5 MHz signal, then you'll probably have some issues, but if you're only accessing them a few times a second, you'll usually be fine. Remember that the comment was "you can kill", not "you will kill".

Link to comment

All of what Yair said is true, and one additional point:

Within dataflow, LV's compiler knows that it can make certain optimizations. For example, if you do something inside a loop, LV can examine the operation and decide, "Hey! I only need to do this once... I'll just move that calculation outside the loop." But with a reference, that optimization cannot be done because the source of the data, the reference, *might* have been changed in some other diagram somewhere. So the data gets recalculated every time even though the result is actually going to be the same each time, but LV can't know that because the data is by reference. There are other compiler optimizations that LV can do for dataflow that it cannot do for references, and these will become substantially more common in the next two LV versions, and probably into the indefinite future.

Link to comment

What it does allow are deadlocks, which is what AQ was refering to. If you want a simple example, think of this psuedocode:

A{Lock (Data)B()Unlock (Data)}B{Lock (Data)...Unlock (Data)}

Does anyone else find it interesting that Yair used a text program example to illustrate an issue with graphical programming? Are references really more suited for text languages? Hmmm.

Link to comment

I wasn't illustrating an issue with graphical programming. I was illustrating deadlock, which can be found anywhere in life (the plumber won't come to fix the leak until the builder comes to tear the wall down, and the builder won't come until the plumber comes and turns off the water. Deadlock). I wanted a simple example which involved a function call and I wanted to clearly show the lock-unlock part AND I didn't have LV open. All those combined led to that.

Link to comment

Does anyone else find it interesting that Yair used a text program example to illustrate an issue with graphical programming?

Nope. It's all about choosing a communication method that best illustrates the idea one is presenting. The time it takes to model your idea is one of the factors in determining the best communication method. I figure maybe 10 seconds for Yair to type that in. I know I couldn't create a deadlock situation in Labview and get it uploaded to my post in 10 seconds without a lot of practice. If you also consider that illustrating a deadlock in Labview requires more ancillary stuff that complicates the model, the choice of text pseudocode is clearly the right one.

What I find interesting is that his use of pseudocode struck you as interesting. wink.gif Is it possible you've been enjoying NI Week a bit too much? beer_mug.giftongue.gif

Are references really more suited for text languages? Hmmm.

I assume this comment is intended to spawn some discussion as I can't imagine NI removing references from Labview. No queues, no property or invoke nodes, no scripting... there would be chaos in the streets! ("Dogs and cats living together...") Anyway, I'll discuss.

References do not exist in a 'pure' data flow language (as I understand the term.) Labview is not a pure data flow language; it is a language based on data flow. Data flow is great for certain types of programs but there are lots of things you can't do without violating it, such as passing information between parallel loops. Labview must expose references if NI wants its usefulness to grow.

The way I see it, Labview has an extremely good high-level api. We see it in every demo where data is acquired and plotted in 10 seconds of programming. It also has a good low-level api. Lots of useful frameworks can be built using the existing references. (Queues, vi server, etc.) Where Labview suffers is in the mid-level api. That's why people have spent so much time building the various OOP frameworks or trying to figure out how to compensate for the lack of native Interfaces. wink.gif

Giving us the DVR is defninitely a step in the right direction. NI just obsoleted a bunch of home-rolled frameworks designed to provide the same functionality. Hopefully NI will continue to fill out the mid level api so we can focus on building applications instead of frameworks. (Although I find designing frameworks far more interesting than designing applications.)

Link to comment
  • 2 weeks later...

On my top-level front panel I have quite a few controls and indicator a number of which need updating from lower in the code (as we all often do).

A lot of my style to tidy things up was to cluster common control / indicators together, I would then create references to these clusters and other controls / indicators on the front panel. All these references would then themselves be clustered together and, in the JKI state machine world these clusters of references would then going to shirft registar so they could be accessed everywhere by just pulling them out of the cluster as and where required.

You can also create a case in your state machine called: "Update UI", then pull the values out using a "Get Data" Method. Then just write the data to the UI using local variables. I know that this may not cover all your scenarios, but it's the method I use most often. For some reason I feel dirty when I use control references.

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
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.