11-03-2015 10:35 AM
Can someone describe use cases for the "Load and Retain on First Call" option presented in the "Call Setup" dialog? Or, for that matter, explain just what that option actually does?
According to the help documentation:
Note If you select the Reload for each call option or the Load and retain on first call option, LabVIEW continues to load the subVI if the block diagram of the caller VI is in memory. If you open the caller VI in edit mode, LabVIEW loads the block diagram of the caller VI and therefore loads the subVI as well. To avoid loading the subVI, do not open the block diagram of the caller VI. Call the caller VI as a subVI, and close the front panel window and block diagram of the caller VI. |
Forgive my ignorance, but I don't really understand what it means to say "the subVI does not load until the caller needs it". When I select this option in LV2013SP1, it replaces with a statically-linked call by reference node. Because of that static linkage, the referenced subvi is still loaded into memory when I open the calling VI in the IDE. The memory profiling of the calling VI doesn't seem to be reduced at all (in fact, in my test example, it actually *increased*). So I don't see the point of that option.
--
I am asking because in one of my applications, we have many cookie-cutter VIs that are essentially different view UIs, and each calls a swiss-army-knife subvi that encapsulates all the UI updating logic. Over time, that (reentrant) subvi called by the various views has grown more and more complex (lots of LVOOP to handle updating different classes of indicators, etc), to the point where each of these UI VIs takes a long time to load into memory. So simple edits to the VIs become really cumbersome as the IDE has to load the thousands of dependencies (and recompile most of them every time--thanks, LabVIEW!).
I was debating about replacing the dependency-laden subvi with by-reference calls to try to improve edit-time performance. I thought it might be nice to be able to just swap the call setup option on all instances to "load and retain on first call", but that doesn't appear to get what I'm looking for. I'll probably try doing an explicit "Open VI Reference" using VI path and a strict (but not static) VI reference to see if that helps (and then just make sure the referenced VI is included in any EXE builds), but I'd still like to know what I'm missing with this option.
11-03-2015 10:46 AM - edited 11-03-2015 10:48 AM
Normally when you load a VI, all of the SubVIs that are used by it (read: on the block diagram) are loaded into memory as well.
If you have a SubVI that might not get called at all during the execution of your program (like a configuration window?), then ticking the 'Load and Retain on First Call' option will save on the memory footprint of your application by not loading it into memory until it is called.
Essentially you're trading off responsiveness (loading the VI from disk takes time) against having a smaller memory footprint.
The difference between this and calling by VI reference using the VI path I guess is that once the VI has finished executing, you can release the memory again by closing the reference (and you have the additional complexity of call by reference).
11-03-2015 10:54 AM
@Sam_Sharp wrote:
If you have a SubVI that might not get called at all during the execution of your program (like a configuration window?), then ticking the 'Load and Retain on First Call' option will save on the memory footprint of your application by not loading it into memory until it is called.
I see that in the help documentation, but somehow it's not clicking for me. As an example:
So it still appears to load Subvi.vi even though I haven't actually hit the Run button on Caller.vi. So what is that "load and retain on first call" option actually doing? Is it something that will only help in a built executable?
11-03-2015 10:57 AM
...It would only make sense to me if the "Load and Retain on First Call" primitive was not statically-linked to the VI it is calling. If it required a VI Path input, then I could see how it would be helpful. But I don't see what it is doing if it is still statically linked to the VI being called by reference.
11-03-2015 11:03 AM - edited 11-03-2015 11:04 AM
@TurboPhil wrote:
- Watched as it still pulled in all the dependencies of Subvi.vi at edit time
I think that's the key thing here - in the documentation it says that "if you open the caller VI in edit mode, LabVIEW loads the block diagram of the caller VI and therefore loads the SubVI as well"
If you put your Caller.VI as a SubVI on another VI, it then wouldn't load the SubVI with all of your dependencies.
11-03-2015 11:04 AM
If the front panel of the VI that contains the 'Call and Retain' subVI call is opened in the IDE, the editor will load the subVI and all of its dependencies. The dependencies will not be loaded (unless the subVI is called) in the following two scenarios:
1. The calling VI is being loaded and run dynamically.
2. The calling VI is a built EXE.
So assuming this app will eventually be built into an EXE, you would see the load time benefits there. If you are looking to speed up your edit time development, then the Open VI Reference -> Call By Reference approach that you already mentioned is your best bet.
11-03-2015 11:08 AM
@TurboPhil wrote:
@Sam_Sharp wrote:
If you have a SubVI that might not get called at all during the execution of your program (like a configuration window?), then ticking the 'Load and Retain on First Call' option will save on the memory footprint of your application by not loading it into memory until it is called.
I see that in the help documentation, but somehow it's not clicking for me. As an example:
- I created a new VI called "Caller.vi"
- I placed on its block diagram a subvi (call it "Subvi.vi") that pulls in a lot of dependencies
- I set the call setup for Subvi.vi as "Load and Retain"
- Saved Caller.vi
- Quit LabVIEW
- Reopenen LabVIEW
- Opened Caller.vi
- Watched as it still pulled in all the dependencies of Subvi.vi at edit time
So it still appears to load Subvi.vi even though I haven't actually hit the Run button on Caller.vi. So what is that "load and retain on first call" option actually doing? Is it something that will only help in a built executable?
Yes, That is what I believe you are seeing. The IDE needs to load the vi to keep compiling the callers. The exe built from your project may have some memory optimizations available with the static vi linkage. Usually, these option settings are unnoticable for the executable unless you have (for example) a gajillion instances of a callee that is re-enterant pre-allocate clones. For non-reenterant vis or "normally" recursive vis this option does little. (I THINK that is why the switch is buried so deep on the RCM) You seldom need to worry about it unless you are doing something funky.
11-03-2015 11:22 AM
@Sam_Sharp wrote:
@TurboPhil wrote:
- Watched as it still pulled in all the dependencies of Subvi.vi at edit time
I think that's the key thing here - in the documentation it says that "if you open the caller VI in edit mode, LabVIEW loads the block diagram of the caller VI and therefore loads the SubVI as well"
If you put your Caller.VI as a SubVI on another VI, it then wouldn't load the SubVI with all of your dependencies.
Huh. You're right! That's not at all what I would have expected.
So I guess I might play around with adding the two-levels-of-indirection design pattern to replace all the direct subvi calls of our many-dependencies subvi and see how that affects IDE and RTE performance....