"If I want to reduce the size of my program, why not use a full-fledged Win32 EXE compressor? That will make my EXE much smaller than with StripReloc! Why did you even bother making it?"
Many fail to realize (or simply aren't told) that there are significant downsides to using EXE compressors such as ASPack and UPX. In my opinion, EXE compression is not something that should be generally applied without serious consideration. Let me explain why.
In DOS, when you started a program, all of its code got loaded from disk into memory and stayed there until the program terminated. If there was not enough available memory to load the entire program, you'd receive an "out of memory" error.
Modern multitasking OSes such as Windows 95/98 and NT use what is called a "virtual memory" system. When programs start, all of their code is not loaded into memory immediately upon startup, as was the case with DOS programs. Instead, only portions of the code being actively executed are stored into memory. For example, say your program has a Print option on its menu, and code behind it that handles the printing. This code will only be loaded into memory once the Print feature is first selected by the user. And if after the code is loaded into memory the Print feature is not used for a while the system will "discard" the code, freeing the memory it occupied, if another application desperately needs memory. This is part of a process called "paging" and is completely transparent to the program.
Another way paging under Win32 conserves memory is it causes multiple instances of a program (or DLL) to share the same memory for code. In other words, under normal circumstances there is no real difference in the amount of physical memory allocated for code between starting 100 instances of a program and starting one instance.
If all Win32 programs behaved like DOS programs, loading everything into memory and keeping it there until the program terminated and also not sharing any memory between multiple instances, you can probably imagine how quickly physical memory could run out on systems with a limited amount, causing disk swapping to start.
Yet this is precisely what current Win32 EXE compressors do to your EXE's/DLL's! They completely go against the OS's paging system by decompressing all code into memory and keeping it there until termination. And because code isn't stored in a "raw" format in the EXE file (i.e. the same way it is stored in memory), the OS is unable to share code between multiple instances.
Many choose to use an EXE compressor assuming it the ultimate weapon against code bloat. But I have to ask: Which is less expensive and more abundant, hard disk space or memory? Is it really worth increasing your application's memory requirements just to save a few kilobytes of disk space?
I have heard many cases of people compressing their MS Office EXE's, and decided that would be a decent "real world" memory usage test. So I compressed the MSACCESS.EXE program from Office 2000 with UPX and compared the memory usage figures in NT 4.0's Task Manager against the original MSACCESS.EXE. Here are the (surprising) results:
File Size Process "Commit Charge Total" "Commit
"Mem Usage" difference difference
1 instance 1 instance 20 instances
--------------------------------------------------------------------------uncompressed 4,677,686 2580 KB 1084 KB 25396 KB
UPX 0.82 2,436,096 6852 KB 6192 KB 126968 KB
From the 1-instance results shown above, compressing MSACCESS.EXE makes it waste around 5MB of memory. Not that bad, but fairly significant.
As for the 20-instance results, you read correctly, it is no typo! 20 instances of a compressed MSACCESS.EXE uses 100MB more memory than 20 instances of an uncompressed MSACCESS.EXE. My test-bed has 256MB of memory so it didn't max out. But good luck doing that on a 64MB system! :-)
To start 20 instances of MSACCESS.EXE I used a 20-line batch file, with each line reading: "START MSACCESS.EXE". Worthy of note is starting 20 instances of the compressed MSACCESS.EXE took noticably longer than the uncompressed MSACCESS.EXE (approximately 4 seconds vs. 1.5), which I suppose is attributable to the lack of code sharing between the instances and the time it takes decompress the code. This shows that even with a smaller file size, compression doesn't always make programs start faster.
Since I wanted the test to focus on code only, I used these switches with UPX: --compress-exports=0 --compress-icons=0 --compress-resources=0. I originally intended to test with ASPack as well, but when I tried running ASPack on MSACCESS.EXE it wouldn't start at all. I am sure the results would be on par with UPX though, since I did tests with other programs (which I did not record) and found this to be the case.
This article is not in any way meant to "bash" the authors of EXE compression programs; it is simply meant to fill in the facts they do not provide. Yes, EXE compression can serve a good purpose when used responsibly. But, at the same time there are many cases when it can produce an undesirable and, on the surface, not immediately noticable result as shown in the preceding test.
I'm using UPX now. It helps me a lot.
I agree with your opinion.