Jump to content

Splash screens and dynamic loading


mje

Recommended Posts

I've done splash screens before, but they've not really served a purpose other than branding so their implementation really didn't matter from a performance perspective.

Now I have an application which seems to take quite a bit of long time to load up, to the point where users regularly wonder, "Hmm, did I actually double click that? Better try again." More than once I've been right next to the person and told them, "No just be patient, it will show up." only to watch them try again and again to click that darned icon. Well at least I haven't set allowmultipleinstances=true in the ini file. Yet.

I know there will be a constant time as the LabVIEW RTE spins up which is independent of the actual executable I create in LabVIEW. But does the size of my executable also affect load times? I'm under the impression that the whole thing must load, so if it's larger a splash screen can't be shown either way until the entire application has been loaded into memory. I might be wrong here. My current application is at 44 MB, this doesn't seem too large to me...

Has anyone played around with dynamically loading their core application logic from outside of the executable to see if that reduced time to display a splash screen? I figure the best way to do this is have the bulk of my code in a LabVIEW built DLL, then have a shell of a LabVIEW exe display the splash screen and proceed to take its time loading the DLL, after which the splash screen hides itself? The DLL will not be statically linked, a path will be built to it at run time. Or is this road fraught with peril? I've never actually built a DLL in LabVIEW, this might be interesting.

  • Like 1
Link to comment

I've done splash screens before, but they've not really served a purpose other than branding so their implementation really didn't matter from a performance perspective.

Now I have an application which seems to take quite a bit of long time to load up, to the point where users regularly wonder, "Hmm, did I actually double click that? Better try again." More than once I've been right next to the person and told them, "No just be patient, it will show up." only to watch them try again and again to click that darned icon. Well at least I haven't set allowmultipleinstances=true in the ini file. Yet.

I know there will be a constant time as the LabVIEW RTE spins up which is independent of the actual executable I create in LabVIEW. But does the size of my executable also affect load times? I'm under the impression that the whole thing must load, so if it's larger a splash screen can't be shown either way until the entire application has been loaded into memory. I might be wrong here. My current application is at 44 MB, this doesn't seem too large to me...

Has anyone played around with dynamically loading their core application logic from outside of the executable to see if that reduced time to display a splash screen? I figure the best way to do this is have the bulk of my code in a LabVIEW built DLL, then have a shell of a LabVIEW exe display the splash screen and proceed to take its time loading the DLL, after which the splash screen hides itself? The DLL will not be statically linked, a path will be built to it at run time. Or is this road fraught with peril? I've never actually built a DLL in LabVIEW, this might be interesting.

From my experience it's not so much the size of the file. It's the size of the hierarchy. If you have 1 VI that is 44MB it will load a lot faster than 10,000 VIs @44MB. Although I would want to debug the former tongue.gif. A splash screen means that you only have a very small hierarchy to load before you can display something. It also gives you the opportunity to "incrementally" load you application For example, you may have a "hardware check". In running that, you have loaded quite a few VIs that you probably use in the main app (and done something useful) without having to wait for the whole app to load.

Link to comment

I actually had the same trouble. I was able to do a splash screen without having to use to exe or dll...

If you create a vi that is your splashscreen, use it to load the main vi of your application dynamically, and make this splashscreen the main vi of your built application, then the splashscreen shows up right away (because the main vi is a few bytes only). You just need a notifier or something like that to tell the splashscreen to stop runing when your application is loaded.

I did that with a 20MB applicationand it works great, the splashscreen shows up in 3 seconds.

Link to comment

I actually had the same trouble. I was able to do a splash screen without having to use to exe or dll...

If you create a vi that is your splashscreen, use it to load the main vi of your application dynamically, and make this splashscreen the main vi of your built application, then the splashscreen shows up right away (because the main vi is a few bytes only). You just need a notifier or something like that to tell the splashscreen to stop runing when your application is loaded.

I did that with a 20MB applicationand it works great, the splashscreen shows up in 3 seconds.

I agree, this method is the way to go. All of the files are in the same exe too so it's more contained then having 2 exes.

I use a VI called Startup.vi that I use to dynamically call the other VIs (designated as a "Startup VIs" in the build). In the "Always Included" section I include the Splash Screen.VI and my main program VI.

Bruce

Startup.vi

Link to comment

From my experience it's not so much the size of the file. It's the size of the hierarchy. If you have 1 VI that is 44MB it will load a lot faster than 10,000 VIs @44MB. Although I would want to debug the former tongue.gif.

I actually had the same trouble. I was able to do a splash screen without having to use to exe or dll...

If you create a vi that is your splashscreen, use it to load the main vi of your application dynamically, and make this splashscreen the main vi of your built application, then the splashscreen shows up right away (because the main vi is a few bytes only). You just need a notifier or something like that to tell the splashscreen to stop runing when your application is loaded.

I did that with a 20MB applicationand it works great, the splashscreen shows up in 3 seconds.

Thanks folks, that's good to know. It is what I've done in the past, but haven't gotten around to doing it yet as the splash screen is pretty low on the priority list. I'll throw something together tonight before I queue up the next build to see how much difference it makes.

As for 10,000 VIs, well, I'm still shy of that thankfully. But this is the first project where I've used OOP for everything and the sheer number of VIs for the project is still quite staggering compared to my previous ones. Currently 44% of my VIs are simple read/write accessors for my objects. Right there's one of the reasons the hierarchy has grown so much.

Link to comment

Well it worked great, thanks for the feedback. My splash screen appears within milliseconds of launching the application. I wasn't aware that having VIs included in the exe does not cause them to "load" (for lack of a better word) if not used.

Link to comment
  • 2 weeks later...

BTW: don't use fade in on a splash screen if your app will normally be run remotely using RDP. For some reason, fades take a long time to transmit over RDP and the effect is mostly lost.

Well for fading you have to use alpha shading and alpha shading has the ostensible property of requiring the retransmission of the entire affected area with every step of the continuous shading effect. That is a lot of bitmap data! RDp or VNC or whatever similar functionality has a lot of optimization built in to reduce the amount of data that needs to be transmitted. I'm sure RDP transmits the actual GDI drawing commands rather than bitmap data whenever possible and when transmitting bitmap it most likely will optimize to only transmit the parts that change between picture changes. Yet with fading in EVERYTHING changes constantly!!

Maybe they will at some point transmit the fading as a drawing primitive too, so the actual transmitted data is a lot less, but for now it is a bitmap transfer over and over again. And because it is a rather cosmetic only feature they sure won't declare it as top priority item as long as there are other areas that still need some improvement too.

Link to comment

OK so here is my perennial question: How can this be done WITHOUT having to use any OpenG?frusty.gif

Make your own OpenG substitutes. Develop VIs with the same functionality needed.

There's only 1 OpenG VI anyway and it's not really even needed.

Edited by bmoyer
Link to comment

Now that's a really great idea -- who'd havve thunk'd it?

How about a little help, like what does "Fit VI Windows to Largest Dec_ogtk.VI do and, perhaps more importantly, how does it do whatever do do it do do...(esp with a 0 argument...)....please?yes.gif

I think you're making a mountain out of an mole hill since this isn't a required VI, but the VI finds the largest decoration on its caller's front panel and then fits the window around the decoration. The 0 argument refers to the border around the decoration.

Bruce

Edited by bmoyer
Link to comment

OK, thanks for the info. NOW I can do a workaround.

< begin soapbox section >

Remember I don't even have "ogtk" on my system and so had no way of knowing what that VI did, esp given that the VI in question only had one input (an int) and no outputs (except for Error In/Out) there was no way for me to discern what that VI did, esp with a truncated name. Maybe it was "...get the largest decimal..."...."...and set it to 0..."; or maybe it was "launch ALL the missiles". It's easy to forget that, if do have the relevant toolkit installed but you're emailing someone who doesn't, they probably can't even see some things that are very obvious to you.

< end soapbox section >

Thanks again! thumbup1.gif

Link to comment

; or maybe it was "launch ALL the missiles".

laugh.gif

I want one of those VIs! I can use it when my "mute manager" vi fails.

But I know what you mean. I find it a bit "irksome" (not only in labview but in other languages too) that it is assumed you have 3rd party dependencies installed.

Link to comment

OK, thanks for the info. NOW I can do a workaround.

< begin soapbox section >

Remember I don't even have "ogtk" on my system and so had no way of knowing what that VI did, esp given that the VI in question only had one input (an int) and no outputs (except for Error In/Out) there was no way for me to discern what that VI did, esp with a truncated name. Maybe it was "...get the largest decimal..."...."...and set it to 0..."; or maybe it was "launch ALL the missiles". It's easy to forget that, if do have the relevant toolkit installed but you're emailing someone who doesn't, they probably can't even see some things that are very obvious to you.

< end soapbox section >

Thanks again! thumbup1.gif

Oh, sorry about the misunderstanding, I assumed that since you knew it was from the OpenG toolkit that you had some experience with it. I got confused when you continued asking about it after I stated that it wasn't needed for the functionality of the VI.

Sorry 'bout that,

Bruce

Link to comment

Yes i could have made it clear that I don't have OpenG on my system but I've talked about that so much in the past that I just assumed it was known. And we all know what happens when we assume....

Yes, and I too was hopeful about the "launch ALL the missiles" possibility....rolleyes.gif

Link to comment

I've done splash screens before, but they've not really served a purpose other than branding so their implementation really didn't matter from a performance perspective.

FWIW this is what I do.

I do it for the reasons you stated - to have time to load the main application and do any initialising I need before showing the UI.

This is the general approach for most applications.

As I do a lot of smaller applications so I decided to write some reuse code and have a generic splash screen engine.

When requirements dictate, I just start with an engine template and go from there.

This is my project, it has two important VIs

Launcher - which is not statically coupled to the application hierarchy

VI Tree - contains all other Top Level VIs (not Launcher)

post-10325-0-19399900-1301795340_thumb.p

This makes the Build Spec very simple and does not need to be changed.

post-10325-0-12935200-1301795334_thumb.p

I then create a Splash Screen for each application that can look like whatever (note: toolbar only shown in dev environment)

post-10325-0-41397200-1301795344_thumb.p

The BD code looks like this - this is the reuse code. I just configure it with the Main VI and UI VI.

post-10325-0-87931400-1301795329_thumb.p

The Engine does its stuff. Launches the Main VI in the background

post-10325-0-38692100-1301795320_thumb.p

Does some fading out or other screen effects based on a Timer

post-10325-0-09986200-1301795401_thumb.p

Then due to the RTE exiting if a FP is not in memory, the application does a check and waits for the UI's FP to be loaded. This means I have time to initialize the UI etc... before showing it.

post-10325-0-14640300-1301795324_thumb.p

Pretty basic I know, but it works.

I have other apps where the Splash Screen can create a log of the session, checks for driver version (DAQmx, dotNET) etc...

I would like to add more features into the reusable code that I have in these other applications when I have the time.

Link to comment

Pretty basic I know, but it works.

I have other apps where the Splash Screen can create a log of the session, checks for driver version (DAQmx, dotNET) etc...

I would like to add more features into the reusable code that I have in these other applications when I have the time.

Good idea about using a VI tree!

I do something pretty similar (without the vi tree). Only I also have a "config" file that tells the loader what to load (I usually have modules that need to check 3rd party hardware as well as DAQ etc, and feed that back to the splash so you see "Loading....[module name]") - they change from project to project)

Link to comment

I do something pretty similar (without the vi tree). Only I also have a "config" file that tells the loader what to load (I usually have modules that need to check 3rd party hardware as well as DAQ etc, and feed that back to the splash so you see "Loading....[module name]") - they change from project to project)

Cool. I have done stuff where the Main App sends Status Messages to the Splash Screen. Can you go into detail about how the hierarchy works here?

Does the Splash Screen load the modules, then open the Main App so th modules stay in memory, then the Splash Screen goes out of memory etc... ??

Cheers

-JG

Link to comment

Cool. I have done stuff where the Main App sends Status Messages to the Splash Screen. Can you go into detail about how the hierarchy works here?

Does the Splash Screen load the modules, then open the Main App so th modules stay in memory, then the Splash Screen goes out of memory etc... ??

Cheers

-JG

Pretty simple really.

The two main points are that the main VI's FP is hidden and it sends a message to the splash to tell it it's loaded.. You can either allow it to load in the background, or load it sequentially (I prefer the latter in case hardware checks fail).

The splash screen itself just loads a config file (usually a section in the main app coinfig), iterates through the file list, dynamically loading (but not closing the ref) on each iteration. You can wait til finished or not depending if you want it sequential or background loading. When it gets to the last one in the list it shows it's panel if the "ready message was received (queues work best for that) As each module is loaded, it remains in memory so you get incremental loading of sub-vis and when the splash closes, any that are only used by the start-up modules will be disposed of and any that are used by the main app will remain (that's why I don't like namespacing and generally prefer llbs or directories over lvlibs).

The key really is dynamic loading which means the splash is very quick to show regardless of the number or size of modules it needs to start up. Comms from the modules can be anything you like, queues, events even pass a string ref via thier front panels when you launch them. I tend to use named queues though (see my Non OOP version of the .Message queue and replace the A,B with the vi name or Dispatcher for my most used architecture which revolves around 1 VI).

Link to comment
  • 1 year later...

I think Rammer's question is more detailed ... he asks LabVIEW to load a top-level Vi. Can he get any sort of progress information about where LV is in the load process and display a progress bar?

Rammer, the answer is no, not in general. We had a new hire join the LV team during the 2012 release cycle, and one of the initial "small" projects he was given to get started with our code base was to try to design such a progress bar system, both for use within LV's internal dialog and possibly exposing hooks for you to create such a progress bar in your code. He ended up pulling in a rather large portion of the LabVIEW team, trying to find a decent solution.

There's a fundamental logical barrier to doing this: when a VI loads, there's no way for the top-level VI to have any idea how many subVIs it will end up loading as its full hierarchy loads in. The group who worked on this tried many many approaches to get around this lack of knowledge and still produce a progress bar that only moves forward and doesn't end up with the 99%-and-holding problem. Nothing was ever particularly satisfactory.

We concluded the only valid solution is on an application-by-application basis. If you just open a reference to your top-level VI, that will load all the VIs in memory. But you could open a reference to one of its deep subVIs, thus only loading that subtree. Then open a reference to another layer up, then another layer up, and you would update your own progress bar after each of those Open VI Reference calls, with the knowledge of what percent of your VI hierarchy that particular open represented.

That new hire moved on to do other projects within 2012, but he continues to check out other apps and strategies for handling this problem generally, so maybe something will pop up in the future, but at the moment, no good ideas are on the table. Note that any strategy that gives us a load progress bar but ultimately makes load take a longer time, like preflighting all the subVIs, is off the table... the last thing LabVIEW needs is to *add* load time in the dev environment when we've made good strides these last couple releases with *subtracting* it!

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.