summaryrefslogtreecommitdiff
path: root/ldso
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2017-03-15 16:50:19 -0400
committerRich Felker <dalias@aerifal.cx>2017-03-15 16:50:19 -0400
commita393d5cc8d22b628fcc1da1b3a2cdae42ca643a9 (patch)
treee6399bb0a600c8e24817b7d4397defb28f391bcd /ldso
parent8cba1dc46c8f29261aa441e70bac798f2c2c0f58 (diff)
downloadmusl-a393d5cc8d22b628fcc1da1b3a2cdae42ca643a9.tar.gz
precalculate gnu hash rather than doing it lazily in find_sym inner loop
this change was suggested based on testing done by Timo Teräs almost two years ago; the branch (and probably call prep overhead) in the inner loop was found to contribute noticably to total symbol lookup time. this change will make lookup slightly slower if libraries were built with only the traditional "sysv" ELF hash table, but based on how much slower lookup tends to be without the gnu hash table, it seems reasonable to assume that (1) users building without gnu hash don't care about dynamic linking performance, and (2) the extra time spent computing the gnu hash is likely to be dominated by the slowness of the sysv hash table lookup anyway.
Diffstat (limited to 'ldso')
-rw-r--r--ldso/dynlink.c10
1 files changed, 2 insertions, 8 deletions
diff --git a/ldso/dynlink.c b/ldso/dynlink.c
index 178fe27e..5361b844 100644
--- a/ldso/dynlink.c
+++ b/ldso/dynlink.c
@@ -258,18 +258,12 @@ static Sym *gnu_lookup_filtered(uint32_t h1, uint32_t *hashtab, struct dso *dso,
static struct symdef find_sym(struct dso *dso, const char *s, int need_def)
{
- uint32_t h = 0, gh, gho, *ght;
- size_t ghm = 0;
+ uint32_t h = 0, gh = gnu_hash(s), gho = gh / (8*sizeof(size_t)), *ght;
+ size_t ghm = 1ul << gh % (8*sizeof(size_t));
struct symdef def = {0};
for (; dso; dso=dso->syms_next) {
Sym *sym;
if ((ght = dso->ghashtab)) {
- if (!ghm) {
- gh = gnu_hash(s);
- int maskbits = 8 * sizeof ghm;
- gho = gh / maskbits;
- ghm = 1ul << gh % maskbits;
- }
sym = gnu_lookup_filtered(gh, ght, dso, s, gho, ghm);
} else {
if (!h) h = sysv_hash(s);