Popular Post UnlikelyNomad Posted July 15, 2017 Popular Post Report Posted July 15, 2017 I've been working a lot lately with by-reference architectures that still cooperate completely with LabVIEW's implementation of OOP and polymorphism. I've also recently taken an interest in trying to speed up development with secondary providers (similar to GOOP) to enable automatic creation of accessor VIs hidden behind the DVR, automatic creation of the private data type and constructor/destructor, etc. within the project window. I'm generally not a fan of the extra stuff that goop adds in to classes, I'd prefer to keep the source code looking as close to a normal class as possible. That said, I've started on my first ever XNode and it's a cross between an unbundle by name node and the -> operator in C. It functions just like a normal UBN, however it was also pull items out of DVRs. Having to plop down a UBN to pull out the reference from the class, an in place node to dereference, and then another UBN to pull the data out gets tiresome after about the 100th property VI gets written. So far I've gotten the node drawing completed (except for data type coloring of the labels), the type inferencing from the input wire, and the popup menu for selecting an item. Next up will be the menu selection code so that the names will finally show up in the terminals! Then I get the daunting task of scripting up the GenerateCode ability >_> Anyone interested in something like this? Following this will be a match to the Bundle by Name node that serves the same purpose except to write the items. 3 Quote
mje Posted July 15, 2017 Report Posted July 15, 2017 Property nodes already do this? Granted it requires implementing the property, but I'm generally not a fan of pulling data from class wires via the cluster primitives as it makes it hard to track where data is consumed. Quote
UnlikelyNomad Posted July 15, 2017 Author Report Posted July 15, 2017 The key here is working with the DVRs and to speed up the boiler plate effort of multiple unbundle by names and an in place structure. Quote
UnlikelyNomad Posted July 15, 2017 Author Report Posted July 15, 2017 The above bit is what gets tedious to setup for all of those property VIs, this would get used inside those VIs for outside access but for a lot of stuff I do I try to avoid the overhead of an additional VI call just to pull out a data value. Here's a clarification of the boilerplate I'm eliminating: Quote
mje Posted July 15, 2017 Report Posted July 15, 2017 Oh right. I jumped to objects by analogy to the c languages, completely forgetting the hard boundary between clusters and objects in LV. Quote
smithd Posted July 18, 2017 Report Posted July 18, 2017 (edited) Well the nice thing about his is that you dont have to copy the entire data structure, just the portions you care about. Note that he unbundles inside the IPE structure. For known names that you want to support (like always unbundle the thing called "waveform") the VIM would work, but its not arbitrary like the xnode could be. Edited July 18, 2017 by smithd Quote
DTaylor Posted July 18, 2017 Report Posted July 18, 2017 (edited) I think it's extremely useful. I added DVR support to the latest version of LV-Signals which does something very similar: It only works with DVRs of clusters, and it looks like yours works with DVRs in general. Check out LV-Signals if you get a chance, the original use was to use it with LV-Create-Signals.xnode, which creates a DVR and a value change event for each element in the cluster. https://github.com/erdosmiller/lv-signals Edited July 18, 2017 by DTaylor 1 Quote
DTaylor Posted July 18, 2017 Report Posted July 18, 2017 On 7/15/2017 at 0:25 PM, UnlikelyNomad said: Then I get the daunting task of scripting up the GenerateCode ability >_> When you do this give LV-Scripting a chance: https://github.com/erdosmiller/lv-scripting It has similar functionality to the LAVA Scripting Library: https://lavag.org/files/file/54-scripting-tools/ , but with a heavy emphasis on ease of use for code generation. The package has a dozen or so examples which likely cover everything you need for your XNode. Quote
hooovahh Posted July 18, 2017 Report Posted July 18, 2017 So cool, I would definitely use an XNode that does this. Yes the VIM could work with the issues already mentioned, with copying the whole cluster in memory just to grab one element. Props for the idea, and DTaylor's suggestion. Quote
UnlikelyNomad Posted July 18, 2017 Author Report Posted July 18, 2017 So we'll effectively call this the first time I've heard of VI Macros. Is there some list somewhere of all the neat tricks NI is hiding from us? Quote
hooovahh Posted July 18, 2017 Report Posted July 18, 2017 Oh sorry it was renamed Maleable VI, official feature in 2017 but was implemented as a custom XNode shipped with LabVIEW since around 8.2. http://zone.ni.com/reference/en-XX/help/371361P-01/lvupgrade/labview_features/ VI Macro discussion before 2017 made VIMs official. https://lavag.org/topic/19163-vi-macros/ It has some shared functionality with XNodes (type propagation for inputs and outputs) but other custom things like right click, adding removing terminals, and changing node size and icon at edit time can only be done as an XNode, not a VIM. Quote
UnlikelyNomad Posted July 18, 2017 Author Report Posted July 18, 2017 Thanks to @smithd and @DTaylor for pushing me back to a property I had missed, I can now type inspect classes! Now that I know that what I was trying to accomplish is possible it's time for some code cleanup and implementation of the scripting. Wish me luck. Quote
UnlikelyNomad Posted July 18, 2017 Author Report Posted July 18, 2017 18 hours ago, infinitenothing said: Maybe VIM could help? I use a lot of reference applications for things like buffers, etc. where pulling out everything everytime would become prohibitive. (As others have stated about my unbundle being inside the IPE). Perhaps the compiler would see the other items aren't pulled out and not copy everything, but if it copied my two gigs of full rate 50khz data when all I wanted was the current data size: boom. Memory fault. Ultimately this XNode is going to become part of a palette of functionality that aids in development of by-reference designs that go beyond just type matching and maybe even someday others start using these and I never have to inherit code where a class instance stores state data in a FG, especially when that FG isn't part of the class. Preview of other coming attractions: Generics in LabVIEW. (With type restrictions!) All of these features will build on what I learn getting this "simple" introduction to XNodes working. Quote
infinitenothing Posted July 18, 2017 Report Posted July 18, 2017 FYI, I just ran a quick experiment (see code below). Watching profiler and task manager, it appears the compiler is smart enough not to copy the string. 1 Quote
hooovahh Posted July 18, 2017 Report Posted July 18, 2017 Was debugging enabled on the VI when it was ran? I assume probing the cluster wire would force the string to be copied into another memory location. Anyway that does sound good since one VIM that takes a few minutes to write could perform some of the same functionality as the XNode. Still would require an unbundle by name, but a Read-Only DVR function could be pretty useful. I think I made one during the 2017 beta replacing the icon now that I think about it. Quote
infinitenothing Posted July 18, 2017 Report Posted July 18, 2017 It works with debug on too. If I try and probe, I see a memory increase and UI slowness. Quote
UnlikelyNomad Posted July 18, 2017 Author Report Posted July 18, 2017 Was the compiler smart enough that it never put the string into the cluster in the first place? /snicker Quote
smithd Posted July 18, 2017 Report Posted July 18, 2017 (edited) Interesting, the same holds even if you do the following: Pull out the string and read array size pull out string and use split string (at char 0xFF) but only read offset Inside of top (writing loop) in-place manipulate data of string (convert to byte array, replace element 0, byte array to string, rebundle) To force labview to do an allocation, I had to go so far as to pull the data out of the DVR and manipulate it and use the manipulated data (I used the same byte array replace index + split string) . They really did a solid job with the optimization here. 1 hour ago, UnlikelyNomad said: Was the compiler smart enough that it never put the string into the cluster in the first place? /snicker Yes it actually did. And in typical labview fashion there are two copies (one for the data after the for loop, one to bundle it). You can get rid of the unnecessary copy through this embarrassing scheme: As impressive as the DVR optimization is, this is far more common and far more sad Edited July 18, 2017 by smithd Quote
UnlikelyNomad Posted July 18, 2017 Author Report Posted July 18, 2017 (edited) I was testing a buffer I wrote for an application some months ago and pushed nearly 2 gigs of data into it 200 rows at a time and then read back the row count. LabVIEW's memory never went above 350megs. Definitely tricky to benchmark in LabVIEW sometimes. LabVIEW is great because it does a lot of stuff for you. LabVIEW sucks because it does a lot of stuff for you. Edited July 18, 2017 by UnlikelyNomad Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.