LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Built executable including even unreferenced .lvclass members?

With email attachment limits, yes 700 kB might matter, plus it's the principle of the thing. If you need to support a dynamic dispatch architecture (which you only do if you decide to design your program that way). If you do not, then it is literally dead weight. I just reduced my compressed deployment from 6,152 kB to 3,994 kB, a 2 MB, 35% reduction in size, by moving most of my high-level methods out of the class library and up into the project library so that the exclusion rules apply. Leaving that dead code in means that my built exe is more than 50% larger for zero benefit.

 

Yes, there are situations where you want to include all your class functions, such as when you are supporting a plugin architecture with dynamic loading and unloading of VIs, but not every time. I think removing unreferenced class members is just as valid in common use cases as removing unreferenced project library members. It isn't that complicated to attempt to remove unreferenced ones. Dynamic dispatch VI referenced? Include any VIs that are children of that VI. Static dispatch VI not referenced? Safe to remove. So on and so forth. It seems illogical that it isn't even an option to exclude unreferenced class VIs, even if the default would be to include them all.

 

This can obviously lead to a philosophical debate of what a class really is and what belongs inside and outside the class, but I don't feel like a built executable should be obligated to carry dead code around with it. It seems unreasonable to expect that any executable should act like a container for all members of any class it references, unless you also expect to have a mechanism to call these functions at a later time. Why shouldn't you be able to say that you don't need or want to provide support for unspecified situations that may never be realized. I should be able so limit the compiled output to just that which is needed for the executable to perform as designed, not provide for "maybe" use cases.

____
Ryan R.
R&D
Message 11 of 19
(1,790 Views)

Ryan,

 

i never disagreed with you that in your use-case optimizations might be possible. The thing i pointed out is that your use-case is not the only one. Because LV AppBuilder handels ALL cases the same (which is more reliable and easier to maintain!) the requested (possible) optimization is NOT done.

Also, even if you are not dealing with what you call "special cases": You cannot be sure that a co-developer might add things like this in the future into "your" application.....

 

Norbert

Norbert
----------------------------------------------------------------------------------------------------
CEO: What exactly is stopping us from doing this?
Expert: Geometry
Marketing Manager: Just ignore it.
0 Kudos
Message 12 of 19
(1,777 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?


But your class doesn't determine whether inheritance is used or not, any possible child class determines that.  Also, LabVIEW currently does NOT differentiate between statically-called classes and possible dynamically called classes (There could theoretically somewhere be a VI which calls a class dynamically, LabVIEW cannot conclusively prove this never happens.  Even the VI doing this could itself be called dynamically - therefore even a dynamic VI call would require the entire class to be retained).

 

As such, any post-build loaded class may or may not access the static methods of your static class and therefore they cannot be removed.  I wish we could define a class as not allowing dynamic instantiation, then we could talk about these kinds of optimisations as the complicated chack for dynamic instantiation would be no longer required.  I have penned an idea in this direction.

0 Kudos
Message 13 of 19
(1,766 Views)

@Norbert_B wrote:

Ryan,

 

i never disagreed with you that in your use-case optimizations might be possible. The thing i pointed out is that your use-case is not the only one. Because LV AppBuilder handels ALL cases the same (which is more reliable and easier to maintain!) the requested (possible) optimization is NOT done.

Also, even if you are not dealing with what you call "special cases": You cannot be sure that a co-developer might add things like this in the future into "your" application.....

 

Norbert


 

Norbert,

I wasn't trying to suggest that my use case was more valid than the majority of others, I just think the app builder can and should be smarter without significant risk. As for a codeveloper, I can be sure. I can with all certainty say that nobody will be doing anything remotely resembling a situation where this dead code would cease to be dead code. If the code needed to be updated to support dynamic loading of VIs, then they will be working on the source code and can uncheck the (hopefully future) build option that removes unreferenced class members.


@Intaris wrote:

But your class doesn't determine whether inheritance is used or not, any possible child class determines that.  Also, LabVIEW currently does NOT differentiate between statically-called classes and possible dynamically called classes (There could theoretically somewhere be a VI which calls a class dynamically, LabVIEW cannot conclusively prove this never happens.  Even the VI doing this could itself be called dynamically - therefore even a dynamic VI call would require the entire class to be retained).

 

As such, any post-build loaded class may or may not access the static methods of your static class and therefore they cannot be removed.  I wish we could define a class as not allowing dynamic instantiation, then we could talk about these kinds of optimisations as the complicated chack for dynamic instantiation would be no longer required.  I have penned an idea in this direction.


Intaris,

Why shouldn't LabVIEW be able to eliminate both these possibilities? This is a deployed executable. It is intended to encompass everything needed for the top-level VI to run. LabVIEW knows the inheritance tree, it can see that I have not set the properties of any class to inherit from another class, so strike the inheritance argument. As for differentiating between statically-called and possibly dynamically called classes, why can't LabVIEW prove that no dynamic calls happen? If a VI isn't included in my build spec then it should not be figured into the equation for the purpose of determining dependencies. All the VIs that are part of my build spec are visible to LabVIEW, there are no inherited classes, and all my VI references are strictly typed to boot. If it's impossible for LabVIEW to determine that there is no possible mechanism in my code for loading an unknown VI at run-time, then I fully support your idea of an "uninheritable" attribute that would give the compiler freedom to optimize without accomodating any possible dynamic loading. I think it should be an option - the option to basically say "my program is fully defined and you don't need to look out for surprise dependencies".

 

As it stands now, moving my high-level methods down into a project library would mean that if I wanted to enable dynamic loading that I'd have to set them or their parent folder to "always include" in my build spec. This at least gives me the flexibility to leave them out if I don't want to support dynamic loading. 

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

Just wanted to join the conversation.  I develop OEM style code using LabVIEW.  We've been building a platform of reuseable code, using parent classes.  From project to project, the parent is reused and any unique requirement is handled with dynamically dispatched VIs within child classes.  It is working pretty well, switching from one project to the next is fairly easy and the code reusablity is there.  However, it does look like that every project pulls in every child that it can find or in otherwords, if you add a parent class to the project it is going to pull in all child classes that inherits the parent.  If there was a way to prevent this I would love to know about it.  In my case, project 2 doesn't need to know about project 1's children.  

 

Thanks!

0 Kudos
Message 15 of 19
(1,519 Views)

@RnDMonkey wrote:


Intaris,

Why shouldn't LabVIEW be able to eliminate both these possibilities? This is a deployed executable. It is intended to encompass everything needed for the top-level VI to run. LabVIEW knows the inheritance tree, it can see that I have not set the properties of any class to inherit from another class, so strike the inheritance argument. As for differentiating between statically-called and possibly dynamically called classes, why can't LabVIEW prove that no dynamic calls happen? If a VI isn't included in my build spec then it should not be figured into the equation for the purpose of determining dependencies. All the VIs that are part of my build spec are visible to LabVIEW, there are no inherited classes, and all my VI references are strictly typed to boot. If it's impossible for LabVIEW to determine that there is no possible mechanism in my code for loading an unknown VI at run-time, then I fully support your idea of an "uninheritable" attribute that would give the compiler freedom to optimize without accomodating any possible dynamic loading. I think it should be an option - the option to basically say "my program is fully defined and you don't need to look out for surprise dependencies".

 

As it stands now, moving my high-level methods down into a project library would mean that if I wanted to enable dynamic loading that I'd have to set them or their parent folder to "always include" in my build spec. This at least gives me the flexibility to leave them out if I don't want to support dynamic loading. 


LabVIEW can dynamically load a child class even in a built executable.  So if your class has a method X,Y and Z but you don't use Y or Z ANYWHERE in your code, it must still be included.  This is because you *MAY* want to later load a class dynamically which DOES call Y or Z, them being missing is a problem.  You can even create this child class AFTER compiling your executable, it matters not.  This is why I way that any given code scope CANNOT remove the possibility of a child class floating around.  Child classes are ALWAYS possible.

0 Kudos
Message 16 of 19
(1,514 Views)

I understand what you are saying, but the result is that each project pulls in every piece of code that I ever wrote.  Ok, that might be a little bit of an exaggeration but not too much of one.  Why can't the compiler distinguish between a dynamically dispatched vi with a constant connected to the input verse one with a control connected to it?  If the input is a constant, the it only needs to know about the properties of the connected constant.  If a control is connected, then it would need to know all information.  Obviously it would have to be more complex than that, the compiler should be able to handle nested dynamically dispatched VIs, which in my mind should ultimately be connected to a constant.  Then if you really did want to pull in ALL children classes, you could use a control, which might even give you an interesting opportunity to set the default state.  

 

For me this problem goes beyond excessively large executables.  If I have two customers each with proprietary information, both projects will pull in all files, thus a potential confidentially breach.  If it is an executable maybe we are still OK, but sometimes we do supply source code as an option.  Then what options do I have?

0 Kudos
Message 17 of 19
(1,495 Views)

I think you're doing something wrong with either your project or your build.

 

The original question was regarding unused methods in a given class being included in the executable.  This is explained by my previous post.

 

If you're finding unused classes (the classes not being present in your project OR your code anywhere) being included then you're doing something wrong in your build.  This should not happen and it is also not something I've ever wirnessed happening.  If, somewhere in the depths of your code you have a factory method with all of these classes statically linked than yeah, you're going to have them all included but that kind of mistake needs to be billed to the programmer, not to the compiler.  What I'm saying is that it seems like you have your classes in there as a first dependency somehow.  Eliminate that vampire source and your build will be back to normal.

 

PS Otherwise I agree with the optimisations which could otherwise be made by sealing the classes (not allowing dynamically loading of classes at run-time).  I think I've linked to an idea of mine already in this htread.

0 Kudos
Message 18 of 19
(1,493 Views)

I also just ran into this issue of the app builder grabbing things it can easily tell never get called and bloating up an executable. If there's an idea exchange to add this optimization, I would like to add my vote for it. Even if there's some use case I'm not thinking of where it could be called, the user can just uncheck the "remove unused" build option and that should restore the current "include everything" behavior. Or, the user can add it to the "always included" section of the source files section of the build spec. My current work around strategy is to move the offending bulk of the VI out of the class and call it dynamically or to use a conditional disable.

0 Kudos
Message 19 of 19
(679 Views)