Prelink test results
For most people, the ability of an ELF binary to link itself to arbitrary shared object files is a wonderful ability, or perhaps a source of occasional annoyance when attempting to compile GNOME. For some, however, this is a cause for concern
When an ELF executable is linked to shared objects, it must load these external files into memory and dynamically link them into the binary. As the number of files to which a binary links grows, so does the time spent loading the binary. Under IRIX this problem is offset by rqsall, and in Linux by prelink.
The environment
To see how much prelink could help me, I ran a few tests. A fresh release of Genthree was compiled, and copied to two partitions. The software chosen for testing were the binaries with the greatest number of library dependencies: mozilla-1.4, linked to 30 libraries, gaim-0.68, linked to 29 libraries, gimp-1.3.20, linked to 31 libraries, and gqview-1.3.2, linked to 24 libraries. To ensure consistency in the running time of each of these programs, they were run from a console with no DISPLAY variable set, so that each program would load, attempt to connect to an X server, and promptly exit.
The machine: 700MHz Athlon, 768MB RAM, Linux 2.4.21
One of the two partitions was left untouched, and the other was prelinked. The following was used for /etc/prelink.conf:
-l /usr/bin -l /usr/sbin -l /usr/X11R6/bin -l /usr/X11R6/lib/mozilla-1.4 -l /usr/local/bin -l /usr/lib -l /usr/X11R6/lib -l /usr/X11R6/lib/mozilla-1.4 -l /usr/local/lib
And the following prelink command was run:
prelink -a --ld-library-path='/usr/lib:/usr/X11R6/lib:/usr/local/lib:/usr/X11R6/lib/mozilla-1.4'
Each test was made by rebooting the machine, starting in single user mode, and running the program three times in succession in an attempt to remove caches as a significant factor. The first run from each test is greatly effected by my slow hard drive, but the last two were consistent.
The numbers
| Mozilla | Gaim | Gimp | Gqview | |
|---|---|---|---|---|
| Not prelinked |
real 0m2.258s user 0m0.210s sys 0m0.080s |
real 0m1.301s user 0m0.030s sys 0m0.020s |
real 0m1.375s user 0m0.050s sys 0m0.000s |
real 0m1.257s user 0m0.030s sys 0m0.030s |
|
real 0m0.228s user 0m0.160s sys 0m0.070s |
real 0m0.038s user 0m0.040s sys 0m0.000s |
real 0m0.039s user 0m0.040s sys 0m0.000s |
real 0m0.031s user 0m0.030s sys 0m0.000s |
|
|
real 0m0.228s user 0m0.200s sys 0m0.030s |
real 0m0.037s user 0m0.030s sys 0m0.010s |
real 0m0.039s user 0m0.030s sys 0m0.010s |
real 0m0.031s user 0m0.010s sys 0m0.030s |
|
| Not prelinked, LD_BIND_NOW=1 |
real 0m2.329s user 0m0.230s sys 0m0.070s |
real 0m1.333s user 0m0.090s sys 0m0.010s |
real 0m1.474s user 0m0.070s sys 0m0.040s |
real 0m1.296s user 0m0.050s sys 0m0.000s |
|
real 0m0.284s user 0m0.260s sys 0m0.020s |
real 0m0.077s user 0m0.070s sys 0m0.000s |
real 0m0.099s user 0m0.090s sys 0m0.010s |
real 0m0.061s user 0m0.050s sys 0m0.010s |
|
|
real 0m0.284s user 0m0.250s sys 0m0.020s |
real 0m0.077s user 0m0.080s sys 0m0.000s |
real 0m0.099s user 0m0.090s sys 0m0.000s |
real 0m0.061s user 0m0.050s sys 0m0.010s |
|
| Prelinked |
real 0m1.731s user 0m0.070s sys 0m0.020s |
real 0m1.209s user 0m0.020s sys 0m0.010s |
real 0m1.357s user 0m0.020s sys 0m0.010s |
real 0m1.286s user 0m0.010s sys 0m0.000s |
|
real 0m0.079s user 0m0.060s sys 0m0.020s |
real 0m0.024s user 0m0.020s sys 0m0.010s |
real 0m0.025s user 0m0.010s sys 0m0.020s |
real 0m0.021s user 0m0.010s sys 0m0.010s |
|
|
real 0m0.079s user 0m0.060s sys 0m0.020s |
real 0m0.024s user 0m0.020s sys 0m0.010s |
real 0m0.025s user 0m0.020s sys 0m0.000s |
real 0m0.021s user 0m0.020s sys 0m0.000s |
|
| Prelinked, LD_BIND_NOW=1 |
real 0m1.735s user 0m0.060s sys 0m0.010s |
real 0m1.282s user 0m0.010s sys 0m0.020s |
real 0m1.342s user 0m0.020s sys 0m0.030s |
real 0m1.317s user 0m0.010s sys 0m0.030s |
|
real 0m0.084s user 0m0.050s sys 0m0.030s |
real 0m0.025s user 0m0.010s sys 0m0.020s |
real 0m0.029s user 0m0.010s sys 0m0.020s |
real 0m0.024s user 0m0.020s sys 0m0.000s |
|
|
real 0m0.085s user 0m0.050s sys 0m0.040s |
real 0m0.024s user 0m0.020s sys 0m0.000s |
real 0m0.028s user 0m0.030s sys 0m0.000s |
real 0m0.024s user 0m0.020s sys 0m0.000s |
The conclusion
The amount of speed increase that prelink can offer varies from program to program. Some programs saw a significant decrease in startup time, while others saw little or no measurable decrease. However, even though the results are less than spectacular with certain binaries, the startup time of the prelinked binaries was never worse than that of the non-prelinked binaries, so overall prelink does help. The sometimes noticeable difference in load time when setting LD_BIND_NOW seems to indicate that using prelink could even help the overall feel of a running program by preventing delays after loading while lazily linking a particular function.
The increase in binary sizes was mostly insignificant. mozilla-bin increased from 222048 bytes to 252716, gaim from 819856 to 825632, gimp from 2613528 to 2623328, and gqview from 611820 to 635620. However, since the binaries are being modified, the packaging system will need to be aware of prelink, or a frontend written for prelink aware of the packaging system’s methods of tracking binaries. The prelink documentation claims that prelinking libraries can improve the use of shared memory pages, but this assertion was not tested.