05-02-2012 11:09 AM
I am trying to come up with the most efficient method--both from an execution standpoint, as well as from a development standpoint--for updating indicators on a front panel.
We have an application with multiple windows containing many numeric indicators, representing measurement devices. We also have a subvi that handles performing queries of a central current value table to return the values of devices by name; you pass in an array of devicenames, and it returns an array of values. The standard LabVIEW paradigm for updating indicators would probably be as follows:
In this simplified example, that seems straightforward enough, but it quickly becomes unmanageable if you have to keep adding/removing indicators. It's a constant struggle to make sure that your lookup array and output array indexing matches. In the example above, there's an example of a common subtle mistake. Can you see it?
In order to speed up development and avoid such mismapping issues, we started playing with scripting, and came up with the following paradigm:
In this example, we just place the indicators on the front panel and ensure that the label matches the device. Then we run a script that will place the terminals into cases in a case structure, and generate the lookup string array. So then we can step through the outputs in a for loop, and update the indicators one by one. This method is slightly easier to maintain that the first one, provided you stick to the scripted methods, but if you ever start manually making changes to the devices, cases, or lookup array, you quickly find yourself in a world of confusion as the inevitable mismapping errors start to come up. Further, it is generally frowned upon to update indicators in a case structure like that (anyone in the LV community care to comment on what that is, exactly?).
Recently, I came up with an alternative that I really like, at least for certain cases: if you can bundle all your FP indicators into a single cluster, then you can perform aggregate lookup/update operations:
This way is super nice, since you are guaranteed that the lookup will always be in the correct order. And you don't have to duplicate the indicator labels explicitly on the block diagram. It will even work if you have nested clusters, as long as they are monolithic! However, there are many cases where a given VI does not lend itself to clustering all the front panel indicators together. Particularly if you have them spread out, and have controls nearby (many displays are schematics, with indicators placed where the physical transducers are located, and often there are controls immediately next to them). Sure, you could just create one giant transparent cluster container and toss all your indicators in that, then put any controls on top. But I tend to shy away from floating objects on top of other objects if I can help it. And it is really easy to screw up and accidentally add items to the cluster when you don't mean to...
Ideally, what I would really like is to be able to update all the indicators by reference:
In this example, we just grab all the references once (this is a simplified example, you would probably need to be a little fancier in your traversal to avoid including controls, etc.) and then update the Value property. But, of course, we all know how well LabVIEW handles property node updates, so we defer and undefer FP updates to avoid slowing things down to an absolute crawl. But even doing so, our attempts at using this method have still proven to be pretty darn slow and computationally expensive.
So, my question to you, LabVIEW Community: have any of you come up with a different way to handle this? Do you have any suggestions for updating indicators quickly and efficiently, while maintaining code legibility and scalability? I'm guessing someone out there has come up with some better methods...
05-02-2012 01:30 PM
As a follow-up. I did a quick benchmark test to compare the For Loop/Case Structure method with the By-Reference method. I took one of our GUI windows and copied all the indicators into a separate test VI. In this case, there were roughly 100 individual indicators, all DBL type. Yes, that seems like a lot, but again, we were distributing them over a background image and grouping them based on the data they represent. I stripped out all the graphics and captions to avoid displaying anything proprietary/confidential, so here's how the FP looks now (not pretty, I know):
So, not pretty, to be sure. But you can see it's not a ridiculous number of indicators. [I assure you, with the captions and background images, it looks a lot spiffier]
So, I made two benchmark VIs to update these indicators. First, I did the update-them-in-dedicated-cases-inside-a-for-loop method:
[devicenames have been blurred to protect the innocent]
If I run this as shown, updating all ~100 indicators 100 times, the total update time is roughly 6ms. Not too shabby.
If I try the by-reference method, performance is decidedly crappier:
Even if I defer panel updates throughout the entire update process, as shown above, writing the values to all indicators 100 times takes over 2.3 seconds. That's over 380 times slower!
So, from this example, my main conclusion is that property nodes are not the way to go. It's unfortunate, since they would provide the cleanest and most versatile/scalable mechanism. Unless anyone has come up with better workarounds, or can point out flaws in my implementation...?
05-02-2012 02:17 PM
One option to consider is to only update values which have actually changed. Sometimes I go even further and allow a "deadband" and will only update the display if the value has changed by a certain amount (either a fixed value or a %). If you have 100 values changing as quickly as possible I have a hard time imagining a user comprehending much of it.
Property nodes are notoriously "slow", but my brain (at least) is typically even slower. Values which change rapidly should be in charts or graphs (IMO), and values which change occasionally can possibly be handled using property nodes if you limit the updates to actual value changes.