[LLVMdev] Export maps and -fvisibility-inlines-hidden

Daniel Dunbar
Thu, 28 Aug 2008 23:20:52 -0000

Apologies for the cross-post, this effects both clang and llvm.

I was looking into the startup time of clang on small files
(
http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20080818/007171.html
)
and discovered that a significant amount of our startup time was being
spent in the linker resolving weak symbols. At least on Darwin, this was
actually the dominant factor in our startup time. Our use of C++ means
that by default we tend to have quite a few weak symbols in our binaries.

There are two ways to reduce this startup cost, one start is to use
-fvisibility-inlines-hidden for compilers which support it (GCC). This marks
inline member functions as hidden which means they do not appear as
weak external symbols in the final linked image.

The second is to use an explicit list of exports which is provided to the
linker. For applications like llvm-as which do no loading of plugins the
export list is simply "_main" which is easy to specify.

Here are some timing results on Darwin of versions of clang, llc, and
llvm-as
for each option. The -cur command is the way the current executable is
build, -vih
is the executable compiled with -visibility-inlines-hidden, and -export is
the
executable built with an export list of "_main" only (this subsumes
-fvisibility-inlines-hidden).

These are all Release builds. empty.ll is in fact empty, empty.bc is the
resultant
.bc, and empty.c has one int variable. runN is a program which simply
fork-execs
the given program N times (1000 in this case).

====
# For a baseline:
ddunbar at ddunbar2:rt$ time runN 1000 `which true`
real    0m1.561s
user    0m0.303s
sys    0m1.136s

--- clang ---
# 4152 weak external & defined symbols

ddunbar at ddunbar2:rt$ time runN 1000 ./clang-cur empty.c
real    0m8.398s
user    0m4.708s
sys    0m3.299s

# 1937 weak external & defined symbols
ddunbar at ddunbar2:rt$ time runN 1000 ./clang-vih empty.c
real    0m6.732s
user    0m3.250s
sys    0m3.124s

# 0 weak external & defined symbols
ddunbar at ddunbar2:rt$ time runN 1000 ./clang-export empty.c
real    0m4.998s
user    0m1.781s
sys    0m2.923s

--- llc ---

# 3914 weak external & defined symbols
ddunbar at ddunbar2:rt$ time runN 1000 ./llc-cur -f -fast -regalloc=local
empty.bc
real    0m8.958s
user    0m4.331s
sys    0m4.170s

# 2037 weak external & defined symbols
ddunbar at ddunbar2:rt$ time runN 1000 ./llc-vih -f -fast -regalloc=local
empty.bc
real    0m7.482s
user    0m3.056s
sys    0m3.932s

# 0 weak external & defined symbols
ddunbar at ddunbar2:rt$ time runN 1000 ./llc-export -f -fast -regalloc=local
empty.bc
real    0m6.123s
user    0m1.919s
sys    0m3.775s

--- llvm-as ---

# 1370 weak external & defined symbols
ddunbar at ddunbar2:rt$ time runN 1000 ./llvm-as-cur -f empty.ll
real    0m4.683s
user    0m2.036s
sys    0m2.362s

# 725 weak external & defined symbols
ddunbar at ddunbar2:rt$ time runN 1000 ./llvm-as-vih -f empty.ll
real    0m4.141s
user    0m1.606s
sys    0m2.288s

# 0 weak external & defined symbols
ddunbar at ddunbar2:rt$ time runN 1000 ./llvm-as-export -f empty.ll
real    0m3.376s
user    0m0.969s
sys    0m2.180s

===
The performance difference is rather large for these small files. My
suggestion based on
these results is that we enable -fvisibility-inlines-hidden by default for
platforms which
support it, and add a Makefile flag which allows individual programs to
specify their export
list (probably just as a list of symbols). For simple tools which have no
exports we
would set this to _main.

Seems reasonable?

 - Daniel
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20080828/d28ac8f8/attachment.html>