LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

LVOOP technique for passing classes down to subVIs

Hello LVOOP experts,

 

A quick question regarding performance of LVOOP. I finally got around to implementing something non-trivial with LV classes, just for fun though.

 

If my architecture consists of a state machine, with a typedef'ed shift-registered cluster (containing all my core classes) being passed around the main loop and into subVIs, is there a performance penalty if the classes contain lots of data?

 

My question arises from my only passing knowledge of how LV classes work. As they are byvalue, does this mean ALL the data gets copied/moved between every state, and into every subvi? Or is the compiler smart enough to know that if I am passing the main cluster into a subVI it doesn't necessarily need to make a copy of the data unless I am forking it or something.

 

Fictional example, one of the classes is a data storage and has 1M DBL values in it, is this going to cause lots of memory allocation? (If so then its better probably to not store the data directly in the class, rather have a queue or some other byref storage, right?)

 

Comments appreciated 🙂

n

0 Kudos
Message 1 of 8
(3,831 Views)
My understanding is that LVOOP objects are passed by value. So you would indeed take a hit if you are passing large objects around.


Mark Yedinak
Certified LabVIEW Architect
LabVIEW Champion

"Does anyone know where the love of God goes when the waves turn the minutes to hours?"
Wreck of the Edmund Fitzgerald - Gordon Lightfoot
0 Kudos
Message 2 of 8
(3,819 Views)

Mark Yedinak wrote:
My understanding is that LVOOP objects are passed by value. So you would indeed take a hit if you are passing large objects around.

Thats as much as I suspected, thanks for the confirmation.

 

My big problem is I have not seen a reference implementation of how to do it right. I sure wish NI would provide some intermediate example rather than dog/cat or car/truck.

 

The closest I have seen in DfGrays Xylophone set of tutorials, but then he complicates things by using a singleton type approach (dequeue --> use object --> requeue) and a strange (to me) architecture with lots of registered events and an event structure as one of the cases of the main state machine loop.

 

Does anybody have a non-trivial, but freely distributable example of doing classes the right way? I know there are probably a dozen or so ways of doing it right, but there must be some common ground.

 

I spent the weekend mucking about and have something which I will present once I have tidied it up a bit.

 

But the overhead is probably negligible for non-storage type classes, i.e. the classes that define the

0 Kudos
Message 3 of 8
(3,813 Views)

There isn't a common ground really, but in general, you should treat classes just as you would any other data type. In many cases you can write classes which don't need to be by-ref, meaning that when you split the wire you get a full new copy of the object.

 

In some cases, you do want to have by-ref classes, and then you basically have two options:

 

  1. Have a reference to a common data source inside the cluster (similar to singleton thing, but with a separate queue for each "copy" created in an Init method). The main problem with this is that you lose the ability to have dynamic dispatching.
  2. Create a reference to a single object and pass that reference around to access the object (similar to the singleton, where the object is what is contained inside the singleton and the reference is the queue reference). The main problem with this is that LabVIEW doesn't have a convenient UI to create and manipulate these and that you basically have to create a wrapper VI for each method.

Some things to look at:

 

AQ posted a design patterns document somewhere in this site. It includes some common patterns which can help you.

 

The LAVA forums have a forum for OOP discussions which is rather active. You should go read it, because there's a lot of stuff there which can help you (including a recent thread about which way is better for implementing a by-ref architecture).

 

You should probably check out Endevo's GOOP developer studio. It's a very impressive and useful piece of software which (among other things) allows creating by-ref classes and building classes from UML diagrams.


___________________
Try to take over the world!
0 Kudos
Message 4 of 8
(3,782 Views)

nrp wrote:

Mark Yedinak wrote:
My understanding is that LVOOP objects are passed by value. So you would indeed take a hit if you are passing large objects around.

Thats as much as I suspected, thanks for the confirmation.

 

My big problem is I have not seen a reference implementation of how to do it right. I sure wish NI would provide some intermediate example rather than dog/cat or car/truck.

 

The closest I have seen in DfGrays Xylophone set of tutorials, but then he complicates things by using a singleton type approach (dequeue --> use object --> requeue) and a strange (to me) architecture with lots of registered events and an event structure as one of the cases of the main state machine loop.

 

Does anybody have a non-trivial, but freely distributable example of doing classes the right way? I know there are probably a dozen or so ways of doing it right, but there must be some common ground.

 

I spent the weekend mucking about and have something which I will present once I have tidied it up a bit.

 

But the overhead is probably negligible for non-storage type classes, i.e. the classes that define the


 

HI Mark and Neal (?)

 

The Pass by value story is starting to shape as a misnomer (sp? bad name).

 

1) If I do a Show buffer allocations when a class wire splits, the buffer does not show-up under clusters of array but rather as a scalar.

 

2) You can type cast the class ref as a U32 and you get a number.

 

3) When using Dynamic Dispatching you have to have the class control and indicator on the icon connector, so all of the requirements are present for the sub-VI (method) to work in-place using the bufer that was pointed to by the caller.

 

------------------------------------------------------

 

So passing the data in a class is about the same as when working with clusters. If LV can avoid the copy it will.

 

But where you will take a hit...

 

When we fork a class wire there is a buffer allocated. Too many splits could cause problems. As long as we string together lines of VLOOP methods, they should use the same buffer.

 

BTW:

 

I did have to do a re-write of one of my early LVOOP projects because I was splitting a class with a Image data in it. The re-wire skipped using the class and just passed the image data (via a queue between threads).

 

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 5 of 8
(3,777 Views)

Ben, tst

(yes it is Neil)

 

I don't really want to start with byref, as if byval is good enough for AQ, it ought to be good enough for me to start with!

 

Lately I have been quietly lurking in the OO forum on lava, and I have certainly learned a lot but there is quite a bit of it which goes over my head.

(confession time, I am a forum lurker, silently gathering as much knowledge as possible).

 

Last night I watched the webcast of the intro to LVOOP, and happily it was pretty much as I had sussed out already.

 

Attached is my very rough around the edges first attempt at a non-trivial LVOOP app. Basically trying to implement the timeless game of Pong. Its just the first few steps, but a bit of the framework is there.

 

If anyone has any comments (or suggestions) on my LVOOP implementation I would be most appreciative!

0 Kudos
Message 6 of 8
(3,767 Views)

nrp wrote:

Ben, tst

(yes it is Neil)

...

 

I have certainly learned a lot but there is quite a bit of it which goes over my head.

(confession time, I am a forum lurker, silently gathering as much knowledge as possible).

...


Sorry about the misspelling of your name (now and the next time I do it).

 

RE:WAY over my head

 

Same feeling here! That is why I have started to try and answer LVOOP Q's on this side of the barier using what I learned from there balanced with side reading.

 

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 7 of 8
(3,764 Views)

Attachment, what attachment?

 

This attachment! (attached...)

 

The game is basically functional, can be played with the two slider controls to move the paddles. Its quite tricky playing both players by yourself, and as per the original pong the ball speed increases with each hit.

 

I am still having a little trouble getting my head around the proper way to do things, especially:

 

how to access parent private data from within a child. You can either create public methods in the parent class, or in the child VI you can cast the child object to the parent and then access the data directly using an unbundle. I get the feeling that the latter method is cheating in some way?

 

Implementing this in LVOOP has me as excited as when I got my first functional global (and later Action Engine) working properly 🙂

 

 

Message 8 of 8
(3,748 Views)