views:

2673

answers:

12

Are there any compelling performance reasons to choose static linking over dynamic linking or visa versa in certain situations? I've heard or read the following, but I don't know enough on the subject to vouch for their veracity.

1) The difference in performance between static linking and dynamic linking is usually negligible.

2) (1) is not true if using a profiling compiler that uses profile data to optimize program hotpaths because with static linking, the compiler can optimize both your code and the library code. With dynamic linking only your code can be optimized. If most of the time is spent running library code, this can make a big difference. Otherwise, (1) still applies.

+33  A: 
  • Dynamic linking can reduce total resource consumption (if more than one process shares the same library (including the version in "the same", of course)). I believe this is the argument that drives it its presence in most environments. Here "resources" includes disk space, RAM, and cache space. Of course, if your dynamic linker is insufficiently flexible there is a risk of DLL hell.
  • Dynamic linking means that bug fixes and upgrades to libraries propagate to improve your product without requiring you to ship anything.
  • Plugins always call for dynamic linking.
  • Static linking, means that you can know the code will run in very limited environments (early in the boot process, or in rescue mode).
  • Static linking can make binaries easier to distribute to diverse user environments (at the cost of sending a large and more resource hungry program).
  • Static linking may allow slightly faster startup times, but this depends to some degree on both the size and complexity of your program and on the details of the OSs loading strategy.

Some edits to include the very relevant suggestions in the comments and in other answers. I'd like to note that the way you break on this depends a lot on what environment you plan to run in. Minimal embedded systems may not have enough resources to support dynamic linking. Slightly larger small systems may well support linking, because their memory is small enough to make the RAM savings from dynamic linking very attractive. Full blown consumer PCs have, as Mark notes, enormous resources, and you can probably let the convenience issues drive you thinking on this matter.


To address the performance and efficiency issues: it depends.

Classically, dynamic libraries require a some kind of glue layer which often means double dispatch or an extra layer of indirection in function addressing and can cost a little speed (but is function calling time actually a big part of your running time???).

However, if you are running multiple processes which all call the same library a lot, you can end up saving cache lines (and thus winning on running performance) when using dynamic linking relative using static linking. (Unless modern OS's are smart enough to notice identical segments in statically linked binaries. Seems hard, anyone know?)

Another issue: loading time. You pay loading costs at some point. When you pay this cost depends on how the OS works as well as what linking you use. Maybe you'd rather put off paying it until you know you need it.

Note that static-vs--dynamic linking is traditionally not a optimization issue, because they both involve separate compilation down to object files. However, this is not required: a compiler can in principle, "compile" "static libraries" to a digested AST form initially, and "link" them by adding those ASTs to the ones generated for the main code, thus empowering global optimization. None of the systems I use do this, so I can't comment on how well it works.

The way to answer performance questions is always by testing (and use an test environment as much like the deployment environment as possible).

dmckee
The resource consumption is basically the code space, which as time goes on is less and less of a concern. If 500K of library is shared between 5 processes that's 2MB savings, which is less than .1% of 3GB of RAM.
Mark Ransom
If the library also shares the same virtual mapping (the same physical and virtual address in all processes), doesn't a dynamic link also save TLB slots in the processor's MMU?
Zan Lynx
Also a dynamic link makes it easy to update buggy library code with better versions.
Zan Lynx
@Zan It also makes it easy to add buggy code to a working version.
anon
This doesn't really address the performance implications, but that may be because (1) is true and they are negligible under most circumstances. You did give a very good overview of the practical implications of dynamic vs static linking under normal conditions.
Eloff
+10  A: 

I agree with the points dnmckee mentions, plus:

  • Statically linked applications might be easier to deploy, since there are less or no additional file dependencies (.dll / .so) that might cause problems when they're missing or installed in the wrong place.
stakx
Yup. I got there on the nth edit...
dmckee
+5  A: 

This discuss in great detail about shared libraries on linux and performance impliaction.

nos
+1 for linking to Drepper's DSO howto, which everyone making libraries on Linux should read.
janneb
+8  A: 

1) is based on the fact that calling a DLL function is always using an extra indirect jump. And this is usually negligible today. Inside the DLL there is some more overhead on i386 CPU's because they can't generate position independent code - on amd64 jumps can be relative to the program counter so this is a huge improvement.

2) This is correct. With profile guided optimizations you can usually win about 10-15 percent performance. Now where CPU speed has reached it limits it might be worth doing it.

I would add (3) the linker can arrange functions in a more cache coherent grouping so that expensive cache level misses are minimised. It also might effect the startup time off applications.

And don't forget that with DLL's no dead code elimination can be performed. Depending on the Language DLL code might not be optimal compiled as well. Virtual functions are always virtual because the compiler doesn't know if a client is overwritting it.

For this reasons if there is no real need for DLL's just use static compilation.

Lothar
I like this answer, because it was the only one to address the points I raised in the question.
Eloff
It would be interesting to have references on those DLL technicalities, and a comparison among different operating systems.
UncleZeiv
+8  A: 

G'day,

One reason to do a statically linked build is to verify that you have full closure for the executable, i.e. that all symbol references are resolved correctly.

As a part of a large system that was being built and tested using continuous integration, the nightly regression tests were run using a statically linked version of the executables. Occasionally, we would see that a symbol would not resolve and the static link would fail even though the dynamically linked executable would link successfully.

This was usually occurring when symbols that were deep seated within the shared libs had a misspelt name and so would not statically link. The dynamic linker does not completely resolve all symbols, irrespective of using depth-first or breadth-first evaluation, so you can finish up with a dynamically linked executable that does not have full closure.

HTH

cheers,

Rob Wells
very good point, I've been trying to do this recently with some code I have at work but compiling everything statically proved surprisingly annoying and I just gave up
UncleZeiv
+2  A: 

Dynamic linking requires extra time for the OS to find the dynamic library and load it. With static linking, everything is together and it is a one-shot load into memory.

Also, see DLL Hell. This is the scenario where the DLL that the OS loads is not the one that came with your application, or the version that your application expects.

Thomas Matthews
+2  A: 

It is pretty simple, really. When you make a change in your source code, do you want to wait 10 minutes for it to build or 20 seconds? Twenty seconds is all I can put up with. Beyond that, I either get our the sword or start thinking about how I can use separate compilation to bring it back into the comfort zone.

Hans Passant
I haven't actually benchmarked the difference in compile speeds, but I'd dynamic link if it were significantly faster. Boost does enough bad things to my compile times as it is.
Eloff
+6  A: 

Dynamic linking is the only practical way to meet some license requirements such as the LGPL.

Mark Ransom
+1  A: 

Another issue not yet discussed is fixing bugs in the library.

With static linking, you not only have to rebuild the library, but will have to relink and redestribute the executable. If the library is just used in one executable, this may not be an issue. But the more executables that need to be relinked and redistributed, the bigger the pain is.

With dynamic linking, you just rebuild and redistribute the dynamic library and you are done.

R Samuel Klatchko
+3  A: 

1/ I've been on projects where dynamic linking vs static linking was benchmarked and the difference wasn't determined small enough to switch to dynamic linking (I wasn't part of the test, I just know the conclusion)

2/ Dynamic linking is often associated with PIC (Position Independent Code, code which doesn't need to be modified depending on the address at which it is loaded). Depending on the architecture PIC may bring another slowdown but is needed in order to get benefit of sharing a dynamically linked library between two executable (and even two process of the same executable if the OS use randomization of load address as a security measure). I'm not sure that all OS allow to separate the two concepts, but Solaris and Linux do and ISTR that HP-UX does as well.

3/ I've been on other projects which used dynamic linking for the "easy patch" feature. But this "easy patch" makes the distribution of small fix a little easier and of complicated one a versioning nightmare. We often ended up by having to push everything plus having to track problems at customer site because the wrong version was token.

My conclusion is that I'd used static linking excepted:

  • for things like plugins which depend on dynamic linking

  • when sharing is important (big libraries used by multiple processes at the same time like C/C++ runtime, GUI libraries, ... which often are managed independently and for which the ABI is strictly defined)

If one want to use the "easy patch", I'd argue that the libraries have to be managed like the big libraries above: they must be nearly independent with a defined ABI that must not to be changed by fixes.

AProgrammer
Some OSes for non-PIC or expensive-PIC processors will prepare dynamic libraries to be loaded at a particular address in memory, and if they can do that, they just map in a copy of the library to every process that links with it. That reduces the overhead of PIC a lot.At least OS X and some Linux distributions do this, I'm not sure about Windows.
Andrew McGregor
Thanks Andrew, I didn't knew that some Linux distributions used this. Do you have a reference I can follow or a key word I can search to learn more? (FWIW I had heard that Windows was doing a variant of this, but Windows is too far out of my zone of competence for me mentioning it).
AProgrammer
+1  A: 

On Unix-like systems, dynamic linking can make life difficult for 'root' to use an application with the shared libraries installed in out-of-the-way locations. This is because the dynamic linker generally won't pay attention to LD_LIBRARY_PATH or its equivalent for processes with root privileges. Sometimes, then, static linking saves the day.

Alternatively, the installation process has to locate the libraries, but that can make it difficult for multiple versions of the software to coexist on the machine.

Jonathan Leffler
nice point, albeit slightly offtopic
UncleZeiv
A: 

example of dynamic linking

Nidhi