ELF Prelinking and what it can do for you
By: James Crasta
What is Prelinking?
Prelinking is a process that allows you to speed up the process of dynamic linking. What it does is, through a process of magic that is incredibly complex, but basically it speeds up the relocation process, in loading shared libraries.. by setting preferred load addresses.
What is he talking about, you ask? Well, here's how it goes. Dynamically linked libraries (often referred to as DSO's or in the windows world DLLs) are libraries which are loaded at runtime. The advantage of shared libraries versus static libraries is, that it reduces the size of executables, since each program doesn't need its libraries built in, but will dynamically locate and use it at run time. This adds some overhead, because the address space of the library, instead of being known in advance, has to be mapped at runtime. Another advantage of shared libraries is that due to the magic of copy-on-write, you can save memory when you have multiple programs sharing the same library (though it's not as simple as that.. it is pretty complicated)
Pre-linking sets preferred address space for the libraries to be loaded at. Note they are _preferred_ spaces, and if that address space is not available, then it will use relocation to load it dynamically.. hence pre-linking is not 100% foolproof.
What do I need to prelink?
To prelink, you need at least:
- glibc 2.3.1 or greater
- libelf or elfutils 0.7, though 0.8 is preferred. Latest version as of this writing is 0.84
- Your shared libraries have to be compiled with -fPIC
- the prelink program from ftp://people.redhat.com/jakub/prelink
Okay, so now how do I do it?
First, you need to set up a prelink.conf . This file tells prelink where to search for shared libraries and where to search for apps to prelink if you decide to use the -a feature to prelink everything.
once you have set this up, you are ready to go.
to prelink an executable, simply:
# prelink /path/to/executable
(note that the path must be an absolute path to the program)
The process of prelinking is reversible, to remove the prelinking simply:
# prelink --undo /path/to/executable
These other flags might also be useful to you:
-v verbose, will show all the libraries it is linking
-n dry run, when used with v will compute libraries but not modify any executables
-a Prelinks _all_ executables using a recursive search of the directories in prelink.conf
I wanna see numbers! Does it really help?
Well, the results with prelinking is mixed. I haven't seen any tests where prelinking hurt execution speed, but while some people get spectacular improvements, some people get only minimal improvements. I've combined data from my tests on mozilla and konqueror, along with Jekub Jelinek's tests on konqueror, to see how much elf prelinking really helps.
Tests Without Prelink With Prelink Notes
Mozilla test 1 real 0m1.199s
sys 0m0.020s real 0m1.133s
sys 0m0.020s This test was done by running mozilla with DISPLAY= set to nothing. basically, it just tests the prelinking stage, not the loading and connecting to the X server.
Mozilla test 2 real 0m7.582s
sys 0m0.180s real 0m7.556s
sys 0m0.100s This test was done from the start to finish of mozilla load, with me exiting as soon as mozilla loaded up. It is not really an accurate test since user speed also is a factor here.. but to me (the user) I saw no perceived difference between using prelink and not using it.
Konqueror test real 0m0.906s
sys 0m0.020s real 0m0.923s
sys 0m0.030s I tried the same with konqueror, another huge C++ app with lots of shared libraries, but it seems the time didn't change that much, except for a decent change in user time.. but not a huge difference. Jakub Jelinek seemed to get better results
Jakub Jelinek's Konq test real 0m0.510s
sys 0m0.000s real 0m0.011s
sys 0m0.010s Jelinek seemed to get some really good results in loading konq... I don't know why I wasn't as lucky.
In my tests with prelinking, I have been unable to get any sort of results with it. However, it may work better for you. I guess, the only thing to do is try it. The process is reversible at least. It won't work on just any system though, all the libraries have to be compiled with -fPIC and you need a recent glibc. A recently compiled gentoo will work with prelink enabled, you will have to kludge with other distros.
To prelink or not to prelink?
Prelink theoretically can cause large performance boosts. It avoids a lot of calls to mmap that have to be done in the dynamic linking process. On some systems and with very large programs that load a lot of shared libraries, prelinking in tests has shown speed increases in load time. Keep in note, however, that prelinking only really helps the load time of your applications, for the most part actual runtime speed is not affected.
also note that, in order for prelink to be useful, you need to have all your libraries compiled with fPIC, and be running glibc 2.3.1 or higher. I don't know if this is the case for the major distributions, aside from Gentoo which does support prelinking if you have a recently compiled gentoo setup.
The final word: if you have all the requirements to prelink, and really want to get that speed bost, it's worth a try. else, wait and see if it catches on enough that your distribution will begin prelinking executables for you.
- GlibC 2.3 paper: changes in the new GlibC http://people.redhat.com/drepper/lt2002talk.pdf
- Gentoo Linux Prelink Guide http://www.gentoo.org/doc/en/prelink-howto.xml