LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Built executable including even unreferenced .lvclass members?

For convenience of access scope, I recently added a high-level and some of its associated subVIs to a virtual folder in my class. Yes, I should (and intend to presently) properly set access scope for the things that are causing problems like typedefs, class VIs, etc. The thing I noticed, however, was that a different built executable that uses this class grew by about 700 kB when I made a minor change to it. I've set the build spec to exclude unreferenced files, but I can confirm that when I move my new VIs out of the class that by other built exe goes down in size, thus proving that merely being present in a referenced .lvclass warrants inclusion in any built exe that references the class. What gives? Why can't it remove unused members of class libraries like it can remove unused members of project libraries?

 

I will now be going through the class and trimming it down to what is truly integral to the class, but this seems like a deficiency to me, since there are potentially dozens of high-level class methods that I never use in a given application but that my executable is forced to carry around. This also means, for example, that if a single one of my class methods uses a LabVIEW function that is part of lvanlys.dll, that any built exe will include lvanlys.dll even if it never uses said method.

____
Ryan R.
R&D
0 Kudos
Message 1 of 19
(4,621 Views)

Ryan,

 

just a guess in the blue: LV does not check for child classes. So esp. dynamic dispatch methods must not disappear as the child might override it. Or a child might call into that method.

 

Some optimization might be possible for private items, however optimization is VERY DIFFICULT with plugin architectures. The EXE only contains the base class (parent) while the plugins are stored outside the EXE. So building the EXE never knows if some child classes use "unused" items of the parent class.....

 

Norbert

Norbert
----------------------------------------------------------------------------------------------------
CEO: What exactly is stopping us from doing this?
Expert: Geometry
Marketing Manager: Just ignore it.
0 Kudos
Message 2 of 19
(4,604 Views)

My knowledge of this is a little bit vague, but I believe the reason that all class items are included (even if not called) in the build is that LV doesn't necessarily know which items are going to be required by the class until run-time (e.g. in the case of dynamic despatch...and probably some other reasons).


LabVIEW Champion, CLA, CLED, CTD
(blog)
0 Kudos
Message 3 of 19
(4,594 Views)

Norbert,

I'm not using any dynamic dispatch methods at all - my class doesn't contain any inheritance at all. I don't have a plugin architecture at all, or are you suggesting that the ability to remove unreferenced class members might be a design decision to support the plugin paradigm just in case it is used?

____
Ryan R.
R&D
0 Kudos
Message 4 of 19
(4,590 Views)

Again, it seems like static dispatch VIs could be excluded safely (except in a plugin architecture like Norbert mentions, perhaps).

____
Ryan R.
R&D
0 Kudos
Message 5 of 19
(4,584 Views)

I'm guessing, as i already said 🙂

But you are correct in your understanding: I guess that the AppBuilder deals all lvclass the same because it would be a huge effort to differ between classes which do not have children nor dynamic dispatch vs. large inheritance trees. So it is the easiest solution to ALWAYS keep all stuff of the class as the worst case scenario requires those "unused" items as a static code analysis cannot identify a caller.

 

You are correct that theoretically optimization might be possible, but that is not the "normal" case.

 

Norbert

Norbert
----------------------------------------------------------------------------------------------------
CEO: What exactly is stopping us from doing this?
Expert: Geometry
Marketing Manager: Just ignore it.
0 Kudos
Message 6 of 19
(4,579 Views)

@RnDMonkey wrote:

Again, it seems like static dispatch VIs could be excluded safely (except in a plugin architecture like Norbert mentions, perhaps).


Nope. Imagine a dynamic VI call (no lvclass VI) which has the class as parameter. You cannot know if that dynamic VI calls the "unused" item.

Norbert
----------------------------------------------------------------------------------------------------
CEO: What exactly is stopping us from doing this?
Expert: Geometry
Marketing Manager: Just ignore it.
0 Kudos
Message 7 of 19
(4,573 Views)

@RnDMonkey wrote:

Norbert,

I'm not using any dynamic dispatch methods at all - my class doesn't contain any inheritance at all. I don't have a plugin architecture at all, or are you suggesting that the ability to remove unreferenced class members might be a design decision to support the plugin paradigm just in case it is used?


This.

 

I think it was too complicated to be able to safely determine (based on the class hierarchy / support for dynamic despatch) whether a library item was needed or not so it was safer to include all of the items in the build.

 

What happens if a dynamic despatch VI calls a static VI? Oh yeah, then you need that too!


LabVIEW Champion, CLA, CLED, CTD
(blog)
Message 8 of 19
(4,570 Views)

@Norbert_B wrote:

@RnDMonkey wrote:

Again, it seems like static dispatch VIs could be excluded safely (except in a plugin architecture like Norbert mentions, perhaps).


Nope. Imagine a dynamic VI call (no lvclass VI) which has the class as parameter. You cannot know if that dynamic VI calls the "unused" item.


Isn't this still more of a plugin architecture concern? All methods of my class are statically referenced. I'm not trying to make these VIs accessible later by some unforseen VI. LabVIEW knows which VIs I have placed on my block diagram, and which VIs are placed on their block diagrams, etc. It just doesn't try to resolve anything deeper than the .lvclass level, when it seems like this should be one of those "additional exclusions" settings.

 

Again, I'm deploying an executable. This is my calling VI, therefore LabVIEW should be able to determine the dependencies since every VI is referenced statically. In other words, I do know if that VI calls the unused items, and so should LabVIEW. It looks like NI just decided (wild speculation) that, rather than allow users to [shoot themselves in the foot and] exclude a class member that doesn't have a static reference to it, that they should avoid all risk and always include all class members no matter what. Note that this means anything that is in the class library such as .vit templates, .ico icons, custom probes that serve no purpose with debugging disables, anything. It means that it may not be in your best interest to make a class that is a superset of functionality and/or that includes function templates and examples, unless you don't mind burdening any user of that class with the storage space.

____
Ryan R.
R&D
0 Kudos
Message 9 of 19
(4,556 Views)

@RnDMonkey wrote:

It means that it may not be in your best interest to make a class that is a superset of functionality and/or that includes function templates and examples, unless you don't mind burdening any user of that class with the storage space.


In your case, you mentioned this is 700kb. In this day, is that much space really an issue?

 

A class is more than a collection of functions; it's also a contract that all the methods defined in the class are available. I prefer the safety of knowing that all members of a class get compiled into an executable, over the small amount of space that might be saved by a complicated compiler attempt to remove ones that are unused.

0 Kudos
Message 10 of 19
(4,544 Views)