views:

127

answers:

4

I tried to search, but so far with no luck. Does anyone know a good resource how one should do cold start optimizations?

The app in question is C++/MFC app, compiled with VS2010, full version, with built in profiler available. I have tried to cut down all the extra weight to get the load times acceptable for warm start, but the cold start is simply unacceptable. Sometimes close to 30 secs, and there is nothing that's slow code wise. Cpu loads hit 80% during warm starts, and stay below 20% during cold starts.

I tried to play with delay-load linker settings today, but I don't quite understand how they affect the performance. Also, I tried the executable packer, but the test on VM didn't seemed to be way faster. Is there anything else I could try?

+1  A: 

One thing that might help is to have a look into profile guided optimisation, which reorders the executable so that things load in the most efficient order.

But really you should try and work out where the time's going - sounds like it might be doing a lot of disk access - are you loading a lot of big data (images, etc?). It seems unlikely that it would be purely code loading which is taking so much time.

Have you tried a tool like Procmon (www.sysinternals.com) to see which files are being touched?

Will Dean
That's a very good suggestion, I haven't looked into profile guided optimization before, and somehow I didn't thought of procmon. What also scares me is that there are all kinds of multimedia dll's loaded that I know I don't need. There are two full screens of dll files loaded when I watch the process startup via Process Explorer.
Madman
@Madman: then you should not link with these DLLs, look at your settings in VS and remove them. The more you load, the slower you'll be.
Matthieu M.
@Matthieu - I think the problem is he's not explicity linked those DLLs, they've been pulled in by other parts. But given that IE doesn't take 30 seconds to cold start (and is probably never really cold anyway), it doesn't sound that it's just the web control which is the problem.
Will Dean
+2  A: 

Long cold start times are pure hard disk problems. Finding the DLLs that your program needs. You cannot optimize the hard disk beyond running a defragging tool. Segmenting your program so that DLL loading overlaps UI time is quite difficult. Using COM servers or the linker's /DELAYLOAD option are obvious approaches but it is just not that easy to get a functional UI up on the screen without touching just about anything. Separating classes into DLLs that are triggered by toolbar or menu options is of course possible but MFC doesn't make it that easy with Idle time UI updating (sorry, forgot the exact phrase).

You're not alone, good examples of programs that have this problem too are Microsoft Office and Acrobat Reader. They solve the problem with a very icky hack, they install an 'optimizer' in Run registry key or Startup folder shortcut. Which doesn't do anything but touch all the DLLs so that they are loaded in the file system cache. Giving the EXE a warm start after the user checked her email. I hate them and keep deleting them after they put it back again. But it does improve the user opinion, they'll think it is the email reader that is slow. Or the blasted Windows-shoulda-gotten-a-Mac of course.

That said, 30 seconds is a helluva long time. Do make sure this isn't a problem on just your dev machine, induced by building the binaries over and over again and getting them scattered all over the disk. Run Defraggler. Next, check what all it is doing with the SysInternals' ProcMon utility.

Hans Passant
Is there some sort of optimzation for COM servers? I have multiple COM components - MSXML, MS Web Browser control, and few of internal components that I use in this application, but it seems they are loaded as DLLs in the end anyway.
Madman
Well, sorta. It is just that their DLLs get loaded on demand. By the CoCreateInstance call, it is not an implicit DLL dependency like the ones you get by linking the import .lib. Which are loaded even before your WinMain() can start running. It is very much the same thing as /DELAYLOAD.
Hans Passant
+1  A: 

"I tried to play with delay-load linker settings today, but I don't quite understand how they affect the performance."

When you link to a DLL dependency it loads it up front - when the executable is first loaded. Delay loading is like it suggests, delaying the load until it's actually needed - when a type or method in the DLL is first used by the executable, i.e. you can think of it as lazy initialization at the module level.

The linker is effectively using a stub to LoadLibrary and GetProcAddress. Once the DLL is loaded the stub is overwritten so that calls are made directly to the DLL from then on.

To take advantage of this you need to look at the code paths - which variables or method calls are used conditionally or not on the main screen, in which case they don't need to be loaded up front.

Sean Fausett
But it doesn't help with inherited dependencies, or does it? For example if MS Web browser control decides to import some sort of multimedia/pdf plugin, it will still be loaded during the Web browser component CoCreate call, right?
Madman
Yes, that would be beyond your control; but you could try to delay instantiating the COM object which is the root dependency in this case.
Sean Fausett
A: 

It's doing something, and you don't know what it is. So trying this, and tweaking that, is stabbing in the dark. Asking for guesses, no matter how educated they are, is not much better.

The profiler is better than nothing, but you need to find out what's really going on.

Here's a way to do that.

Certainly loading DLLs can be a big startup problem, but there can be other things going on as well. Examples I've found: Retrieving internationalized character strings (that didn't need to be). Building data structure, windows & controls, then destroying and re-building them as menus and tree-views are being populated. If the tree of abstractions is at all deep, really weird stuff can be happening.

Mike Dunlavey