Like what you hear?
Join forces with Hellebore today!Contact Us
There's two kinds of linking in the world: Static and Dynamic. Which should you choose for your library? The decision on which linking strategy to employ can have a significant impact on application performance.
Often, we use the term compiling to encompass both compiling and linking, but linking is actually a discrete step. A compiler or assembler produces object code. (Usually in the form of .obj files.) Combining these object files into a single library (or executable) is referred to as linking.
On Windows systems, dynamically linked libraries use the file extension .dll. On Linux, dynamically linked libraries are referred to as shared objects and use the file extension .so. Both platforms standardize on the use of the .lib extension for statically linked libraries.
Dynamically linked libraries offer a number of benefits over static linking, but also come with some regrets. There are times when a statically linked library make sense.
When multiple processes load the same library at the same base address, they share a single library instance in memory. When many applications may utilize the same library at the same time, this can be highly beneficial. It reduces the memory footprint of the library code and reduces load time when multiple applications are utilizing it. However, it also ties together all library users on a system, meaning that if one updates the library, all must use the new version. There are situations where this may not be desired. (Try to avoid DLL Hell.)
When any of the implementation of the symbols within a dynamically linked library is updated, applications that utilize them do not need to be recompiled or relinked (so long as the symbol signatures did not change). A statically linked library would require relinking (at a minimum) when symbol implementations change.
Programs written in different languages but which utilize the same calling convention (i.e. cdecl, stdcall, or pascal) can leverage the same dynamically linked libraries.
A shared library's actual performance can be higher because operating systems may choose not to page out memory used by several applications. This OS behavior can result in fewer page faults during application execution. (And paging behavior can be a significant contribution to overall application performance.)
Dynamically linked applications are not self-contained. It may not be obvious which dynamic libraries are being utilized by an application without detailed inspection at runtime (and executing different pathways within the application). Statically linked libraries explicitly include all code necessary to execute and are generally easier to distribute.
Dynamic linking takes time. There must be runtime loading of the library from disk into memory, linking, and then executing. There are times when this can be a significant performance hit to an application. Statically linked libraries do not suffer these specific bottlenecks.
Symbols utilized inside a dynamically linked library may be distributed throughout a virtual address space. This virtual address space distribution means that an application may have to move through many pages to access the specific symbols that it needs and create Translation Lookaside Buffer (TLB) misses. Statically linked libraries, however, bind the references into a program with more address space locality. (Other advanced optimization techniques may improve this even more.)
Dynamically linking libraries takes time and not necessarily a predictable amount of time. Statically linked applications, however, will take a constant time to load. If your application must be highly deterministic within the system that it is executing on (think safety-critical applications), then static linking your application may be worth considering.
To dynamically link a library, the Application Binary Interface (ABI) of the library must be compatible with that of the application attempting to link it at runtime. API compatibility was a significant source of irritation for Windows C++ developers before Visual Studio 2017. Now, modern compilers are sensitive to creating ABI-breaking changes.
It depends (of course). If performance is your key driver when deciding on static vs. dynamic linking, the only real answer is to measure. You may find that some libraries need to be statically linked, while others should be dynamically linked. Even the internal structure of an application can impact this.
Chief Executive Officer
CEO, Hellebore Consulting Group. John has over 20 years of experience in building software for DoD organizations, leading organizational change, and building strong cultures.