Darryl Gove's blog
Graph of libraries used by firefox and thunderbird
Just gathered library usage charts for firefox and thunderbird. The full charts look like:
Firefox
Thunderbird
Neither of which is particularly telling. The reduced charts look much better:
Firefox
Thunderbird
Posted at 03:00AM May 22, 2009 by Darryl Gove in Sun |
Drawing libraries - neater eye-candy!
Chris Quenelle posted an interesting comment to my post which showed the dependencies for StarOffice. As you can see from the mass of lines below, adding more dependency information, using the latest version of ld_dot, into the StarOffice library map did not make the graphic any clearer!
It turns out that the reduction operation that Chris was alluding to is implemented by tred (the "transitive reduction filter", what great technobabble!). This filtering reduces the graph down to something which even looks ok when shrunk down to fit this page:
This clarifies the relationships between the libraries. More importantly it also looks pretty.
Posted at 09:48PM May 20, 2009 by Darryl Gove in Sun | Comments[1]
Libraries (5) - Runtime costs - TLBs
The next consideration when using libraries is that each library will get mapped in on a new virtual page of memory; as shown in this pmap output:
% pmap 60500 60500: a.out 00010000 8K r-x-- /libraries/a.out 00020000 8K rwx-- /libraries/a.out FEEC0000 24K rwx-- [ anon ] FEED0000 8K r-x-- /libraries/lib1_26.so FEEE0000 8K rwx-- /libraries/lib1_26.so FEEF0000 8K r-x-- /libraries/lib1_25.so FEF00000 8K rwx-- /libraries/lib1_25.so FEF10000 8K r-x-- /libraries/lib1_24.so FEF20000 8K rwx-- /libraries/lib1_24.so FEF30000 8K r-x-- /libraries/lib1_23.so FEF40000 8K rwx-- /libraries/lib1_23.so FEF50000 8K rwx-- [ anon ] FEF60000 8K r-x-- /libraries/lib1_22.so FEF70000 8K rwx-- /libraries/lib1_22.so FEF80000 8K r-x-- /libraries/lib1_21.so FEF90000 8K rwx-- /libraries/lib1_21.so FEFA0000 8K r-x-- /libraries/lib1_20.so FEFB0000 8K rwx-- /libraries/lib1_20.so FEFC0000 8K r-x-- /libraries/lib1_19.so ....
There are finite number of TLB entries on a chip. If each library takes an entry, and the code jumps around between libraries, then a single application can utilise quite a few TLB entries. Take a CMT system where there are multiple applications (or copies of the same application) running, and there becomes a lot of pressure on the TLB.
One of the enhancements in Solaris to support CMT processors is Shared Context. When multiple applications map the same library at the same address, then they can share a single context to map that library. This can lead to a significant reduction in the TLB pressure. Shared context only works for libraries that are loaded into the same memory locations in different contexts, so it can be defeated if the libraries are loaded in different orders or any other mechanisms that scramble the locations in memory.
If each library is mapped into a different TLB entry, then every call into a new library is a new ITLB entry, together with a jump through the PLT, together with the normal register spill/fill overhead. This can become quite a significant chunk of overhead.
To round this off, lets look at some figures from an artificial code run on an UltraSPARC T1 system that was hanging around here.
| Experiment | Runtime |
|---|---|
| Application that jumps between 26 different routines a->b->c...->z. All the routines are included in the same executable. | 3s |
| Application that jumps between 26 different routines a->...z. The routines are provided as a library, and calls are therefore routed through the PLT. | 6s |
Application that jumps between 26 different routines a->...z. The routines are
provided as a library, but all are declared static except for the
initial routine that is called by main. Therefore the calls within the library
avoid the PLT. |
3s |
| Application that jumps between 26 different routines a->...z. Each routine is defined in its own library, so calls to the routine have to go through the PLT, and also require a new ITLB entry to be used. | 60s |
Since the routines in this test code don't actually do anything, the overhead of calling through the PLT is clearly shown as a doubling of runtime. However, this is insignificant when compared with the costs of calling to separate libraries, which is about 10x slower than this.
Moving the experiment to look at the impact on CMT systems:
| Experiment | Runtime |
|---|---|
| One copy of this executable per core of an UltraSPARC T1 processor | 1 minute |
| Two copies of this executable per core | 5 minutes |
| Four copies of this executable per core (fully loaded system) | 8 minutes |
Running multiple copies of the application has a significant impact on performance. The performance counters show very few instructions being executed, and much time being lost to ITLB misses. Now this performance is from a system without the shared context changes - so I would expect much better scaling on a system with these improvements (if I find one I'll rerun the experiment).
The conclusion is that care needs to be taken when deciding to split application code into libraries.
Posted at 06:00PM May 20, 2009 by Darryl Gove in Sun |
Libraries (4) - Runtime costs - Procedure Lookup Table (PLT)
Most applications spend the majority of their time running - rather than starting up. So it's useful to look at the costs of using libraries at runtime.
The most apparent cost of using libraries is that calls to routines now go indirectly to the target routine through the procedure look up table (PLT). Unless the developer explicitly limits the scope of a function, it is exported from the library as a global function, which means that even calls within the library will go through the PLT. Consider the following code snippet:
void func2()
{
...
}
void func1()
{
func2();
}
If this is compiled into an executable the assembly code will look like:
func1()
11104: 82 10 00 0f mov %o7, %g1
11108: 7f ff ff f8 call func2 ! 0x110e8
1110c: 9e 10 00 01 mov %g1, %o7
However, if this is compiled as part of a library then the code looks like:
func2()
664: 82 10 00 0f mov %o7, %g1
668: 40 00 40 b9 call .plt+0x3c ! 0x1094c
66c: 9e 10 00 01 mov %g1, %o7
This is a doubling of the cost of the call.
In C it's possible to limit the scope of the function using the static keyword. Declaring func1 as static will cause the compiler to generate a direct call to that routine. The downside is that the routine will only be visible within the source file that defines it. It is also possible to use other methods to limit the visibility of symbols.
Posted at 03:00PM May 20, 2009 by Darryl Gove in Sun | Comments[2]
Libraries (3) - Application startup costs
As can be seen from the previous graphs, even a simple application (like ssh) can pull in a fair number of libraries. Whenever a library is pulled in, the linker has to request memory, load the image from disk, and then link in all the routines. This effort takes time - it's basically a large chunk of the start up time of an application. If you profile the start up of an application, you'll probably not see much because much of this time is basically the OS/disk activity of mapping the libraries into memory.
Of course applications also have start up costs associated with initialising data structures etc. However, the biggest risk is that applications will pull in libraries that they don't need, or perhaps do need, but don't need yet. The best work-around for this is to lazy load the libraries. Of course it's fairly easy to write code that either breaks under lazy loading or breaks lazy loading. It's not hard to work around these issues with care, and doing so can have a substantial impact on start up time.
Posted at 02:01PM May 20, 2009 by Darryl Gove in Sun |
Libraries (2)
Just updated the ld_dot script to include filter libraries. Added a profile for ssh logging into a system, rather than just showing the help message (click the image for the full size version).
Posted at 11:52AM May 20, 2009 by Darryl Gove in Sun |
Libraries
I was talking to Rod Evans about the diagnostic capabilities available in the runtime linker. These are available through the environment setting LD_DEBUG. The setting LD_DEBUG=files gives diagnostic information about which libraries were loaded by which other libraries. This is rather hard to interpret, and would look better as a graph. It's relatively easy to parse the output from LD_DEBUG into dot format. This script does the parsing. The full stesp to do this for the date command are:
$ LD_DEBUG=files date >ld_date 2>&1 $ ld_dot ld_date $ dot -Tpng -o date.png dot.dot
The lines in the graph represent which libraries use which other libraries. Solid lines indicate "needed" or hard links, the dotted lines represent lazy loading or dynamic loading (dlopen). The resulting graph looks like:
More complex commands like ssh pull in a larger set of libraries:
It is possible to use this on much larger applications. Unfortunately, the library dependencies tend to get very complex. This is the library map for staroffice.
Posted at 06:12AM May 20, 2009 by Darryl Gove in Sun | Comments[4]
Relocation Errors
ld.so.1: prog: fatal: relocation error: file ./libfoo.so.1:
symbol bar: referenced symbol not found
Program prog uses libfoo.so.1, and that library has an unresolved dependency on the symbol bar. You can check for this problem using:
$ ldd -d prog
As outlined in the linker guide
Don't, what ever you do, solve it using LD_LIBRARY_PATH!
Posted at 11:56AM Mar 02, 2009 by Darryl Gove in Sun | Comments[9]
Building shared libraries for SPARCV9
By default, the SPARC compiler assumes that SPARCV9 objects are built with -xcode=abs44, which means that 44 bits are used to hold the absolute address of any object. Shared libraries should be built using position independent code, either -xcode=pic13 or -xcode=pic32 (replacing the deprecated -Kpic and -KPIC options.
If one of the object files in a library is built with abs44, then the linker will report the following error:
ld: fatal: relocation error: R_SPARC_H44: file file.o: symbol <unknown>: relocations based on the ABS44 coding model can not be used in building a shared objectFurther details on this can be found in the compiler documentation.
Posted at 09:42AM Oct 16, 2007 by Darryl Gove in Sun |


