Saturday, September 6, 2008

gcc visibility

Newer versions of gcc (e.g. gcc-4.2.3 coming with Ubuntu-8.04) support a feature called visibility. It is explained in detail here. In essence, it lets you declare functions only within the scope of a shared library. The advantages are:

  • Since these functions are not callable from outside, the dynamic symbol table becomes smaller. This speeds up loading (especially in the debugger I assume) and makes a smaller library.


  • If gcc knows at compile-time, that a called function will be in the same shared lib, it can optimize the function call.

My test candidate for this was libquicktime, because it contains lots of private functions (e.g those in lqt_funcprotos.h). Supporting visibility is easy, this is what I did:

  • Let the configure script append -fvisibility=hidden to the CFLAGS if that's supported by gcc.


  • Put the function declarations in public headers between

    #pragma GCC visibility push(default)

    and

    #pragma GCC visibility pop.


  • If there are functions called from outside (e.g. from libquicktime codecs) declared in private headers, add

    __attribute__ ((visibility("default")))

    to their declarations.

In the libquicktime case, this change also revealed some dirty corners (which I cleaned up after compiling with -Wmissing-declarations).

Let's see, what actually changed:

1. Entries in the dynamic symbol table:
# nm -D /opt/gmerlin/lib/libquicktime.so.0.0.0 | grep " T " | wc -l
Before: 866
After: 278

2. Size of the shared library (compiled with standard settings):
Before: 622K
After: 564K

I did some rough speed tests with time qtinfo some_file.mov, but the differences were too little and the measurement method too inaccurate to be significant.

Let's see how this settles down. Doing the same for the gmerlin libraries will be much easier, because they are much cleaner already :)

No comments: