[This is Part I of a two-part series. Part II is available here.]
Load-time performance isnt as critical an optimization now with many people using computers with CPU speeds north of 1 GHz, hundreds of megabytes of RAM, and faster hard drives. However, in some situations, load-time performance can still be a problem if the application uses many DLLs. In this issue of the Windows Q&A newsletter, well take a look at how to optimize the load-time performance of just such an application.
First, its important to understand where a DLL is typically loaded into memory. Inside of every DLL is a base addressthe memory address where the chunk of executable code will start. For executables, the default address is 0x400000, while for DLLs it is 0x10000000. Whenever you create a DLL in Visual Studio, the linker uses 0x10000000 as the base address by default. To see the base address of a DLL (or EXE), you can use the depends utility that comes with the SDK. Simply type depends.exe <dll filename> and youll see something like the following:
Figure 1: Showing the base address of a DLL.
Fortunately, this address can be overidden. The questions that come to mind include where do I override this value and what value do I use as an override?
To override the base address value for a DLL (assuming you have the source code), you can make this change in the Project properties\Linker\Advanced dialog:
Figure 2: Setting the base address via Project properties.
You can use any value you wish for the entry point (base address), but using an address that will be used by the EXE or another DLL will defeat the whole point of this exercise. So you need to specify an address that is available within your process space. Fortunately, Microsoft suggests the following convention for selecting addresses. Using the first letter of the DLL name, look to the right and select an address:
First Letter |
Base Address |
AC
|
0x60000000
|
DF
|
0x61000000
|
GI
|
0x62000000
|
JL
|
0x63000000
|
MO
|
0x64000000
|
PR
|
0x65000000
|
SU
|
0x66000000
|
VX
|
0x67000000
|
YZ
|
0x68000000
|
You might be wondering what you should do if you have multiple DLLs with the same first letter. A brute-force approach would be to evaluate each DLLs size, then start with a given base address value (say, 0x60000000). Add the size of a DLL to the base address and use this new value as the next starting point. You must use the virtual memory size of the DLL, not its EXE file size. Again, we look at the output of depends.exe to get this size:
Figure 3: Determining the virtual memory size of a DLL.
The value I circled in red is the size of a DLL that I created that exports
a single do-nothing
function. Its size is listed as 0x3C000 (245760 in
decimal). So, if I had another DLL for which I wanted to set the base address,
I would add 0x3C000 to my initial starting base address and Id be done.
In the next installment, we'll continue looking at this topic by considering how to create a reference file of fixed address for each DLL in a text file that can be used at link time, and how to use the Rebase.exe tool that comes with the SDK.
Mark M. Baker is the Chief of Research & Development at BNA Software located
in Washington, D.C.
Do you have a Windows development question? Send it to [email protected].