Brandon Moore
Brandon Moore

Reputation: 8780

How to decrease VB6 project startup time / Pinpointing what's taking so long

There are two vb6 applications that I work with. One of them starts up very quickly whereas the other one takes quite a long time. I thought I would do a little analysis to find out why the one takes so long.

So I hit F8 to start at the beginning and I realize that a significant portion of that startup time is actually between the time I hit F8 and the time it highlights the very first line of code.

Which of the following is most likely causing this?

And as a bonus, I would love any ideas on how to more specifically pinpoint the problem if it could be in multiple areas.

Thanks!

Edit: It seems I may have not been clear enough on exactly 'where' the slowdown is occurring. So to make it clear I created the following procedure:

Sub Main()
End Sub

That's it, and it's in a module that contains absolutely nothing besides these two lines. No forms are getting loaded, and while there are other modules with "Dim o as New SomeObject", I know those objects aren't getting instantiated because I know that visual basic doesn't create objects declared this way until you actually use them for the first time.

I believe I have now optimized the startup code as much as is technically possible. Yet it still takes the same amount of time to startup.

Edit 2: I just realized that the compiled application actually starts up reasonably fast. It's just starting it in the ide that takes so long. However, I care a lot more about the speed for me than I do the customer cause they just start it once and leave it running all day whereas I start it a couple dozen times a day.

Upvotes: 9

Views: 3215

Answers (5)

Kelly Ethridge
Kelly Ethridge

Reputation: 1668

This is a super-late answer and not sure if it's still relevant. As the author of large dll's and ocx's, I've run into this problem as well. My only take on it is that I believe it has to do with the registering of the public classes and that they are to be redirected through the VB6 debug library. When the application has finished, it does still take some time to return to the IDE, however, not nearly as long. Probably because it doesn't take as much to delete the registry entries as it does to add them. This is why your dll has the performance issue and not your large exe.

Upvotes: 0

Joel Spolsky
Joel Spolsky

Reputation: 33657

Since you mentioned that you are using Sub Main and so the delay is happening before any forms are loaded, the most likely possibility is that the problem is in the initialization routines of DLLs that you have linked in.

Every DLL exports an entry point function (usually DllMain) which is called right after the DLL is linked in. In VB6 this would be before Sub Main is executed.

It's usually very bad form for DLL authors to do anything significant at all in DllMain for precisely this reason, but many lazy DLL developers do all kinds of work in their DllMain that doesn't really have to be done until later. If you can identify the culprit and rewrite it, that'll fix your problem. If you can't rewrite it, you may at least be able to find a way to dynamically load the DLL instead of linking it.

There is one more thing that you can do to speed up launch time of any Windows application that relies on a lot of DLLs, which is to rebase all the DLLs.

EXEs and DLLs are compiled to assume that they are going to be loaded in memory at certain starting addresses called the Preferred Load Address. For example, a DLL might contain a JMP instruction (basically a GOTO) specifying an absolute address to jump to. The DLL file itself would include a little instruction at the beginning that says to Windows, "Hey, I expect that I'm going to be loaded starting at memory address X, because my code contains a bunch of JMP's to locations that are assumed to be relative to address X." So now Windows will try to put that DLL at location X. But if something else is already using that space, it has no choice but to put it somewhere else, call it Y. When this happens Windows has to go through the entire executable image of the DLL and replace all addresses of the form "X+n" with something that is "X+n+Y-X"... this is called rebasing and it's slow.

If you know in advance that a DLL is going to be loaded with another DLL in your own application, you can increase startup time dramatically by pre-rebasing all the DLLs so that they are non-contiguous.

Upvotes: 5

Deanna
Deanna

Reputation: 24273

How big is the project? It's probably doing an intermediate compile to p-code so it can run it. You may be able to tweak this using the Compile settings in the Options dialog.

Upvotes: 3

Joel Spolsky
Joel Spolsky

Reputation: 33657

That time is probably spent initializing all the objects on the startup form. Do you have a lot of COM objects or UserControls on the startup form? They may, in turn, load other objects that they are using.

The best way to debug this is to remove one object at a time (don't worry about built-in controls, just worry about external objects) from the startup form until you figure out which one is taking the most time at startup. You can then try to speed up the launch time by optimizing the startup code in that object, or at least by deferring the creation of that object until it's actually needed.

Upvotes: 3

Tony Hopkinson
Tony Hopkinson

Reputation: 20320

No way to tell from here every situation is unique.

Could be any or all. Last time I had to deal with someone elses VB code a FormLoad ran a function in a .bas file which set up about twenty records sets...

Aside from really rough measures measuring performamnce in debug is iffy, for VB6, it's even more so as it's interpreting.

You could get a profiling tool, google VB6 Profiling tool.

Or you could add a noddy logger. Bit of code that opens a file appends a time stamped entry to it. Then start whapping calls to it in your code ( don't leave them in when you deploy..)

If you suspect it's formloads, add event handlers for your forms (Load, activate, etc) if they aren't there, and add some dummy code to stick a debug on (or a call to your noddy logger).

This is the important bit. Optimisation 101

Don't guess! Stick a log call in all your major methods, look at what you are being told then drill into it. Add more calls, do more profile analysis, until you have a clear picture of what's going on.

One optimisation at a time, and bench mark it against your base figures, make sure the conditions are the same, that your loop is much faster with 10 records than 10,000 isn't that useful unless you didn't need the other 9990...

It's very easy to break your code when optimising, so have some tests ready to make sure you haven't made it come up with the wrong answer really quick.

Choose your targets, don't spend a week shaving off 1 clock cycle off a function that only gets run once a decade.

And above all unless you find the 9990 records youu didn't need type problem, remember optimisation is a trade off. For instance if all your forms are auto instantiated on running the app and you defer them until say a menu item is selected. At the moment that's a startup delay followed by real quick, deferring, will give yo a quicker start but the function will take longer. Deferring and caching will add complexity to your program.

Also it's very easy for one optimisation to conflict with another, so you load everything so it's there ready, but everything else you do from there is slow because you used up most of your available memory....

HtHs

Upvotes: 0

Related Questions