Sunday, January 14, 2007

Reducing Executable Size

I’ve been trying to figure out how to reduce the size of executables in Visual Studio 2005. After I finished porting from Visual Studio 6 to Visual Studio 2005, the size of my Release executable went from 1.1 MB to 1.7 MB, a 50% increase in size. This was a problem because we have worked very hard to reduce the size of our executables.

I made several changes to the settings. The first change was to go to the Linker section of the project properties, under Optimization, and then set Optimize for Windows98 to “No (/OPT:NOWIN98)”. We don’t have enough win98 users to worry about a negligible performance hit for them. The effect of this was modest, but the change is recommended by several EXE optimization web sites I reviewed.

Next, we had custom optimization settings in VC6 because of a third party library that reacted poorly to being optimized. On the Optimization tab in the Properties for the project, I switched Optimization from “Custom” to “Minimize Size (/O1)” and also set Favor Size or Speed to “Favor Small Code (/Os)”. These two changes reduced the executable from 1.7MB to 1.25MB.

I was able to reduce the size by another 25KB by switching Inline Function Expansion from “Only __inline” to “Any suitable”. This seems counter-intuitive, but I've confirmed the result in several projects.

I had already enabled Whole Program Optimization, so it’s not clear what the net effect of that switch was. However, I discovered while debugging through the disassembly that the compiler will inline just about anything when "Inline Any suitable" and "Whole Program Optimization" are both set. In one case, the compiler determined that a function was only called from one place (presumably a determination made by Whole Program Optimization) and so inlined an entire function into another function, even though it wasn’t labeled __inline and it was a non-trivial function. This wouldn’t affect most situations, but it created very strange results when combined with our code obfuscation engine. I solved the problem by using #pragma to disable optimization for just those functions.

My final result was 1,151,023 bytes for VC6 and 1,260,544 bytes for VS2005, a net ten percent increase in size. My guess is that the increase is due to additional security checks put in by the compiler for buffer overruns.

[Revised 15-Feb-2007 - Fixed typos.]

Saturday, January 13, 2007

ReadyBoost Update

Update 11/3/2008: The problems described in this post were resolved in Windows Vista Service Pack 1

I’ve done some experimenting to find the cause of my ReadyBoost problems. I found that the drive always hangs after the computer comes out of standby. After the computer wakes up, the thumb drive works for a little while and then hangs. The hang is not recoverable and prevents the computer from shutting down.

The solution I found is to select the drive in Explorer and choose Eject. It is not possible to choose Safely Remove Hardware because the device is in use. Then I pull out the thumb drive before putting the computer to sleep.

When the computer wakes up, I put the thumb drive back in. Sometimes Windows automatically starts using the drive again for ReadyBoost, but usually I have to go to the ReadyBoost tab in the Properties dialog and reenable ReadyBoost.

I've sent a technical support request to Apacer but have not heard anything back.