Before everyone goes celebrating, this mainly a benefit to C++ applications. Projects that were using ld properly to strip and manage their shared C libraries won’t see much of a benefit from this.
I can’t think of any disadvantages off the bat. Someone had told me of this possibility before (in order to dynamically load device drivers into a running kernel while minimizing pollution of the global namespace).
It won’t make KDE “go” faster by much, but it will reduce load time of KDE applications by quite a bit. Manual symbol visibility hiding is already being used in places like khtml, but doing it the rest of KDE should help by quite a bit.
A good chunk of kdelibs already has symbol visibility for a few weeks now because of the recent win32 portability patches. MSVC already hides symbols by default.
They tested the TnFOX Boost.Python bindings library.
Load time went from 6 minutes to 8 seconds.
Binary size was reduced by 21MB.
This is an extreme case; the standard ELF binary would export about 200,000 symbols. After the patch, they were only exporting about 18,000 symbols.
The basic concept is that if you have a library made up of multiple source files; you can’t use “static” on all internal procedures. Thus, you can use “__attribute__ ((visibility(“default”)))” to export the symbol and “__attribute__ ((visibility(“hidden”)))” to declare the procudure as private.
This patch is mostly used for loadable libraries. And KDE will get a big boast out of this change (mostly load times).
I know this is an extreme case but how can anyone not have considered this a problem before – if we can get this in extreme cases and let’s say a sec in the average case (since I haven’t benched it yet)..
Anyways, it’s always impressive when someone does work like this.
Oh, it was considere before but never made it to the top of the GCC developer’s priority list. It’s not that big an optimization for the typical case, and GCC needs much more manpower on the core functionality than on peripherial issues.
The benefits of the visibility patch aren’t that big in any case without rewriting some of the source code for libraries that use it, so it’s up to the developer teams to write conformant code. For end users it’s only recommendable to try and compile C++ programs with -fvisibility-inlines-hidden as it only seldom causes trouble and does exhibit some benefits. But don’t expect miracles.
Note that -fvisibility-inlines-hidden only works on the C++ compiler’s command line as C doesn’t have the concept of inline class members.
this patch has been accepted upstream for gcc 4.0, and has appeared in the gentoo gcc 3.4 ebuilds for a bit. it’s also started appearing in the fedora rpms, so if you use fedora core 3 test 2, you already have this patch applied to your gcc. i am unsure of whether or not debian includes it…
For C++ libraries this is a good idea, however for C libraries you should be using symbol versioning anyway, so you might as well control visibility at the same time using a local: * glob.
This is all covered in a “writing shared libraries handbook” I have written, which will be published in the next few weeks I hope.
If you want to *also* mark each symbol manually, or you’re exporting C++ objects from a library, then this technique is a good one.
I don’t do any programming, and know very little about it except what I was taught in college. However I do run linux and like to compile applications from source, then I usually do a strip * in the bin directory of the application. Is there a difference between using strip * and this patch?
This is what you get for not designing a proper module system into your language. The C/C++ system of modules (or lack thereof), is perhaps the biggest 1970’s holdback in existance. It’s barely tolerable for C, and intolerable for C++. The lack of a proper modules system is responsible for the following:
1) Inability to optimize properly across module boundries. Since the compiler is totally disjoint from the linker, you can’t do things like inline a critical function from a shared library, then back out the optimization when the library changes. Even within a single conceptual module (a shared library), interprocedural optimizers like the one in ICC have to use clever mechanisms to get all the intermediate code for each source file in the module in one place.
2) Inability to export templates from shared libraries. It could be done easily be storing the templates as intermediate code, and attaching it to shared libraries, but rust-covered 1970’s era linkers would freak out, so you can’t do that.
3) Necessity of annotating the source code (in PE and now ELF) to specify imports and exports, and the necessity of keeping headers file in sync with source files.
4) The requirement for a C++ compiler to reparse enormous header files over and over again for each source file. Hacks like precompiled headers only mask the problem, and don’t act transparently to the programmer.
But advantages this big must be accompanied by equally big trade offs right? Whats the drawback?
Before everyone goes celebrating, this mainly a benefit to C++ applications. Projects that were using ld properly to strip and manage their shared C libraries won’t see much of a benefit from this.
But overall, it’s very good news…
I can’t think of any disadvantages off the bat. Someone had told me of this possibility before (in order to dynamically load device drivers into a running kernel while minimizing pollution of the global namespace).
Since, KDE is written in C++ so will it benefit this?
It should make KDE (or any QT/C++ app) load faster, at least. How much better, I don’t claim to know.
It won’t make KDE “go” faster by much, but it will reduce load time of KDE applications by quite a bit. Manual symbol visibility hiding is already being used in places like khtml, but doing it the rest of KDE should help by quite a bit.
A good chunk of kdelibs already has symbol visibility for a few weeks now because of the recent win32 portability patches. MSVC already hides symbols by default.
Howdy all
Are there any budding developers out there who have compiled KDE before and after the patch?
Would be interesting to know just how much trimming a large application like this would get from such nice little patch.
They tested the TnFOX Boost.Python bindings library.
Load time went from 6 minutes to 8 seconds.
Binary size was reduced by 21MB.
This is an extreme case; the standard ELF binary would export about 200,000 symbols. After the patch, they were only exporting about 18,000 symbols.
The basic concept is that if you have a library made up of multiple source files; you can’t use “static” on all internal procedures. Thus, you can use “__attribute__ ((visibility(“default”)))” to export the symbol and “__attribute__ ((visibility(“hidden”)))” to declare the procudure as private.
This patch is mostly used for loadable libraries. And KDE will get a big boast out of this change (mostly load times).
I know this is an extreme case but how can anyone not have considered this a problem before – if we can get this in extreme cases and let’s say a sec in the average case (since I haven’t benched it yet)..
Anyways, it’s always impressive when someone does work like this.
Oh, it was considere before but never made it to the top of the GCC developer’s priority list. It’s not that big an optimization for the typical case, and GCC needs much more manpower on the core functionality than on peripherial issues.
The benefits of the visibility patch aren’t that big in any case without rewriting some of the source code for libraries that use it, so it’s up to the developer teams to write conformant code. For end users it’s only recommendable to try and compile C++ programs with -fvisibility-inlines-hidden as it only seldom causes trouble and does exhibit some benefits. But don’t expect miracles.
Note that -fvisibility-inlines-hidden only works on the C++ compiler’s command line as C doesn’t have the concept of inline class members.
This will have a visible benefit on OpenOffice.org startup time. Really.
this patch has been accepted upstream for gcc 4.0, and has appeared in the gentoo gcc 3.4 ebuilds for a bit. it’s also started appearing in the fedora rpms, so if you use fedora core 3 test 2, you already have this patch applied to your gcc. i am unsure of whether or not debian includes it…
This is cool. I wrote flamy article about ELF vs DLL on local newsgroup, and day later someone improved it to direction i meant.
This idea just float in air
Next step will be GCC NOT changing ABI between releases, and soon we will get binary compatible linux
For C++ libraries this is a good idea, however for C libraries you should be using symbol versioning anyway, so you might as well control visibility at the same time using a local: * glob.
This is all covered in a “writing shared libraries handbook” I have written, which will be published in the next few weeks I hope.
If you want to *also* mark each symbol manually, or you’re exporting C++ objects from a library, then this technique is a good one.
Oh, by the way, this won’t do much for prelinked systems I think, but on non-prelinked systems it might prove to be a big win.
I don’t do any programming, and know very little about it except what I was taught in college. However I do run linux and like to compile applications from source, then I usually do a strip * in the bin directory of the application. Is there a difference between using strip * and this patch?
This is what you get for not designing a proper module system into your language. The C/C++ system of modules (or lack thereof), is perhaps the biggest 1970’s holdback in existance. It’s barely tolerable for C, and intolerable for C++. The lack of a proper modules system is responsible for the following:
1) Inability to optimize properly across module boundries. Since the compiler is totally disjoint from the linker, you can’t do things like inline a critical function from a shared library, then back out the optimization when the library changes. Even within a single conceptual module (a shared library), interprocedural optimizers like the one in ICC have to use clever mechanisms to get all the intermediate code for each source file in the module in one place.
2) Inability to export templates from shared libraries. It could be done easily be storing the templates as intermediate code, and attaching it to shared libraries, but rust-covered 1970’s era linkers would freak out, so you can’t do that.
3) Necessity of annotating the source code (in PE and now ELF) to specify imports and exports, and the necessity of keeping headers file in sync with source files.
4) The requirement for a C++ compiler to reparse enormous header files over and over again for each source file. Hacks like precompiled headers only mask the problem, and don’t act transparently to the programmer.