All of lore.kernel.org
 help / color / mirror / Atom feed
From: Peter Zijlstra <peterz@infradead.org>
To: tglx@linutronix.de, jpoimboe@redhat.com
Cc: linux-kernel@vger.kernel.org, x86@kernel.org,
	peterz@infradead.org, mhiramat@kernel.org, mbenes@suse.cz,
	brgerst@gmail.com
Subject: [PATCH v3 20/26] objtool: Optimize !vmlinux.o again
Date: Tue, 24 Mar 2020 16:31:33 +0100	[thread overview]
Message-ID: <20200324160925.107835416@infradead.org> (raw)
In-Reply-To: 20200324153113.098167666@infradead.org

When doing kbuild tests to see if the objtool changes affected those I
found that there was a measurable regression:

          pre		  post

  real    1m13.594        1m16.488s
  user    34m58.246s      35m23.947s
  sys     4m0.393s        4m27.312s

Perf showed that for small files the increased hash-table sizes were a
measurable difference. Since we already have -l "vmlinux" to
distinguish between the modes, make it also use a smaller portion of
the hash-tables.

This flips it into a small win:

  real    1m14.143s
  user    34m49.292s
  sys     3m44.746s

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Josh Poimboeuf <jpoimboe@redhat.com>
---
 tools/objtool/elf.c     |   62 +++++++++++++++++++++++++++++++++---------------
 tools/objtool/elf.h     |   13 ++++++----
 tools/objtool/orc_gen.c |    3 --
 3 files changed, 52 insertions(+), 26 deletions(-)

--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -27,6 +27,22 @@ static inline u32 str_hash(const char *s
 	return jhash(str, strlen(str), 0);
 }
 
+static inline int elf_hash_bits(void)
+{
+	return vmlinux ? ELF_HASH_BITS : 16;
+}
+
+#define elf_hash_add(hashtable, node, key) \
+	hlist_add_head(node, &hashtable[hash_min(key, elf_hash_bits())])
+
+static void elf_hash_init(struct hlist_head *table)
+{
+	__hash_init(table, 1U << elf_hash_bits());
+}
+
+#define elf_hash_for_each_possible(name, obj, member, key)			\
+	hlist_for_each_entry(obj, &name[hash_min(key, elf_hash_bits())], member)
+
 static void rb_add(struct rb_root *tree, struct rb_node *node,
 		   int (*cmp)(struct rb_node *, const struct rb_node *))
 {
@@ -115,7 +131,7 @@ struct section *find_section_by_name(str
 {
 	struct section *sec;
 
-	hash_for_each_possible(elf->section_name_hash, sec, name_hash, str_hash(name))
+	elf_hash_for_each_possible(elf->section_name_hash, sec, name_hash, str_hash(name))
 		if (!strcmp(sec->name, name))
 			return sec;
 
@@ -127,7 +143,7 @@ static struct section *find_section_by_i
 {
 	struct section *sec;
 
-	hash_for_each_possible(elf->section_hash, sec, hash, idx)
+	elf_hash_for_each_possible(elf->section_hash, sec, hash, idx)
 		if (sec->idx == idx)
 			return sec;
 
@@ -138,7 +154,7 @@ static struct symbol *find_symbol_by_ind
 {
 	struct symbol *sym;
 
-	hash_for_each_possible(elf->symbol_hash, sym, hash, idx)
+	elf_hash_for_each_possible(elf->symbol_hash, sym, hash, idx)
 		if (sym->idx == idx)
 			return sym;
 
@@ -205,7 +221,7 @@ struct symbol *find_symbol_by_name(struc
 {
 	struct symbol *sym;
 
-	hash_for_each_possible(elf->symbol_name_hash, sym, name_hash, str_hash(name))
+	elf_hash_for_each_possible(elf->symbol_name_hash, sym, name_hash, str_hash(name))
 		if (!strcmp(sym->name, name))
 			return sym;
 
@@ -224,7 +240,7 @@ struct rela *find_rela_by_dest_range(str
 	sec = sec->rela;
 
 	for_offset_range(o, offset, offset + len) {
-		hash_for_each_possible(elf->rela_hash, rela, hash,
+		elf_hash_for_each_possible(elf->rela_hash, rela, hash,
 				       sec_offset_hash(sec, o)) {
 			if (rela->sec != sec)
 				continue;
@@ -309,8 +325,8 @@ static int read_sections(struct elf *elf
 		sec->len = sec->sh.sh_size;
 
 		list_add_tail(&sec->list, &elf->sections);
-		hash_add(elf->section_hash, &sec->hash, sec->idx);
-		hash_add(elf->section_name_hash, &sec->name_hash, str_hash(sec->name));
+		elf_hash_add(elf->section_hash, &sec->hash, sec->idx);
+		elf_hash_add(elf->section_name_hash, &sec->name_hash, str_hash(sec->name));
 	}
 
 	if (stats)
@@ -394,8 +410,8 @@ static int read_symbols(struct elf *elf)
 		else
 			entry = &sym->sec->symbol_list;
 		list_add(&sym->list, entry);
-		hash_add(elf->symbol_hash, &sym->hash, sym->idx);
-		hash_add(elf->symbol_name_hash, &sym->name_hash, str_hash(sym->name));
+		elf_hash_add(elf->symbol_hash, &sym->hash, sym->idx);
+		elf_hash_add(elf->symbol_name_hash, &sym->name_hash, str_hash(sym->name));
 	}
 
 	if (stats)
@@ -456,6 +472,14 @@ static int read_symbols(struct elf *elf)
 	return -1;
 }
 
+void elf_add_rela(struct elf *elf, struct rela *rela)
+{
+	struct section *sec = rela->sec;
+
+	list_add_tail(&rela->list, &sec->rela_list);
+	elf_hash_add(elf->rela_hash, &rela->hash, rela_hash(rela));
+}
+
 static int read_relas(struct elf *elf)
 {
 	struct section *sec;
@@ -503,8 +527,7 @@ static int read_relas(struct elf *elf)
 				return -1;
 			}
 
-			list_add_tail(&rela->list, &sec->rela_list);
-			hash_add(elf->rela_hash, &rela->hash, rela_hash(rela));
+			elf_add_rela(elf, rela);
 			nr_rela++;
 		}
 		max_rela = max(max_rela, nr_rela);
@@ -531,15 +554,16 @@ struct elf *elf_read(const char *name, i
 		perror("malloc");
 		return NULL;
 	}
-	memset(elf, 0, sizeof(*elf));
+	memset(elf, 0, offsetof(struct elf, sections));
 
-	hash_init(elf->symbol_hash);
-	hash_init(elf->symbol_name_hash);
-	hash_init(elf->section_hash);
-	hash_init(elf->section_name_hash);
-	hash_init(elf->rela_hash);
 	INIT_LIST_HEAD(&elf->sections);
 
+	elf_hash_init(elf->symbol_hash);
+	elf_hash_init(elf->symbol_name_hash);
+	elf_hash_init(elf->section_hash);
+	elf_hash_init(elf->section_name_hash);
+	elf_hash_init(elf->rela_hash);
+
 	elf->fd = open(name, flags);
 	if (elf->fd == -1) {
 		fprintf(stderr, "objtool: Can't open '%s': %s\n",
@@ -676,8 +700,8 @@ struct section *elf_create_section(struc
 	shstrtab->changed = true;
 
 	list_add_tail(&sec->list, &elf->sections);
-	hash_add(elf->section_hash, &sec->hash, sec->idx);
-	hash_add(elf->section_name_hash, &sec->name_hash, str_hash(sec->name));
+	elf_hash_add(elf->section_hash, &sec->hash, sec->idx);
+	elf_hash_add(elf->section_name_hash, &sec->name_hash, str_hash(sec->name));
 
 	return sec;
 }
--- a/tools/objtool/elf.h
+++ b/tools/objtool/elf.h
@@ -70,17 +70,19 @@ struct rela {
 	bool jump_table_start;
 };
 
+#define ELF_HASH_BITS	20
+
 struct elf {
 	Elf *elf;
 	GElf_Ehdr ehdr;
 	int fd;
 	char *name;
 	struct list_head sections;
-	DECLARE_HASHTABLE(symbol_hash, 20);
-	DECLARE_HASHTABLE(symbol_name_hash, 20);
-	DECLARE_HASHTABLE(section_hash, 16);
-	DECLARE_HASHTABLE(section_name_hash, 16);
-	DECLARE_HASHTABLE(rela_hash, 20);
+	DECLARE_HASHTABLE(symbol_hash, ELF_HASH_BITS);
+	DECLARE_HASHTABLE(symbol_name_hash, ELF_HASH_BITS);
+	DECLARE_HASHTABLE(section_hash, ELF_HASH_BITS);
+	DECLARE_HASHTABLE(section_name_hash, ELF_HASH_BITS);
+	DECLARE_HASHTABLE(rela_hash, ELF_HASH_BITS);
 };
 
 #define OFFSET_STRIDE_BITS	4
@@ -127,6 +129,7 @@ struct section *elf_create_rela_section(
 int elf_rebuild_rela_section(struct section *sec);
 int elf_write(struct elf *elf);
 void elf_close(struct elf *elf);
+void elf_add_rela(struct elf *elf, struct rela *rela);
 
 #define for_each_sec(file, sec)						\
 	list_for_each_entry(sec, &file->elf->sections, list)
--- a/tools/objtool/orc_gen.c
+++ b/tools/objtool/orc_gen.c
@@ -111,8 +111,7 @@ static int create_orc_entry(struct elf *
 	rela->offset = idx * sizeof(int);
 	rela->sec = ip_relasec;
 
-	list_add_tail(&rela->list, &ip_relasec->rela_list);
-	hash_add(elf->rela_hash, &rela->hash, rela_hash(rela));
+	elf_add_rela(elf, rela);
 
 	return 0;
 }



  parent reply	other threads:[~2020-03-24 16:11 UTC|newest]

Thread overview: 89+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-03-24 15:31 [PATCH v3 00/26] objtool: vmlinux.o and noinstr validation Peter Zijlstra
2020-03-24 15:31 ` [PATCH v3 01/26] objtool: Introduce validate_return() Peter Zijlstra
2020-03-25  8:39   ` Miroslav Benes
2020-03-26 10:08   ` [tip: core/objtool] " tip-bot2 for Peter Zijlstra
2020-03-24 15:31 ` [PATCH v3 02/26] objtool: Rename func_for_each_insn() Peter Zijlstra
2020-03-25  8:43   ` Miroslav Benes
2020-03-26 10:08   ` [tip: core/objtool] " tip-bot2 for Peter Zijlstra
2020-03-24 15:31 ` [PATCH v3 03/26] objtool: Rename func_for_each_insn_all() Peter Zijlstra
2020-03-25  8:44   ` Miroslav Benes
2020-03-26 10:08   ` [tip: core/objtool] " tip-bot2 for Peter Zijlstra
2020-03-24 15:31 ` [PATCH v3 04/26] x86/kexec: Use RIP relative addressing Peter Zijlstra
2020-03-25  9:34   ` Miroslav Benes
2020-03-26 10:08   ` [tip: core/objtool] " tip-bot2 for Peter Zijlstra
2020-03-24 15:31 ` [PATCH v3 05/26] x86/kexec: Make relocate_kernel_64.S objtool clean Peter Zijlstra
2020-03-24 20:55   ` Josh Poimboeuf
2020-03-25  9:56   ` Miroslav Benes
2020-03-26 10:08   ` [tip: core/objtool] " tip-bot2 for Peter Zijlstra
2020-03-24 15:31 ` [PATCH v3 06/26] objtool: Optimize find_symbol_by_index() Peter Zijlstra
2020-03-25 10:01   ` Miroslav Benes
2020-03-26 10:08   ` [tip: core/objtool] " tip-bot2 for Peter Zijlstra
2020-03-24 15:31 ` [PATCH v3 07/26] objtool: Add a statistics mode Peter Zijlstra
2020-03-25 10:10   ` Miroslav Benes
2020-03-26 10:08   ` [tip: core/objtool] " tip-bot2 for Peter Zijlstra
2020-03-24 15:31 ` [PATCH v3 08/26] objtool: Optimize find_section_by_index() Peter Zijlstra
2020-03-25 10:12   ` Miroslav Benes
2020-03-26 10:08   ` [tip: core/objtool] " tip-bot2 for Peter Zijlstra
2020-03-24 15:31 ` [PATCH v3 09/26] objtool: Optimize find_section_by_name() Peter Zijlstra
2020-03-25 10:18   ` Miroslav Benes
2020-03-26 10:08   ` [tip: core/objtool] " tip-bot2 for Peter Zijlstra
2020-03-24 15:31 ` [PATCH v3 10/26] objtool: Optimize find_symbol_*() and read_symbols() Peter Zijlstra
2020-03-25 10:20   ` Miroslav Benes
2020-03-26 10:08   ` [tip: core/objtool] " tip-bot2 for Peter Zijlstra
2020-03-24 15:31 ` [PATCH v3 11/26] objtool: Rename find_containing_func() Peter Zijlstra
2020-03-25 10:21   ` Miroslav Benes
2020-03-26 10:08   ` [tip: core/objtool] " tip-bot2 for Peter Zijlstra
2020-03-24 15:31 ` [PATCH v3 12/26] objtool: Resize insn_hash Peter Zijlstra
2020-03-25 10:21   ` Miroslav Benes
2020-03-26 10:08   ` [tip: core/objtool] " tip-bot2 for Peter Zijlstra
2020-03-24 15:31 ` [PATCH v3 13/26] objtool: Optimize find_symbol_by_name() Peter Zijlstra
2020-03-25 10:25   ` Miroslav Benes
2020-03-26 10:08   ` [tip: core/objtool] " tip-bot2 for Peter Zijlstra
2020-03-24 15:31 ` [PATCH v3 14/26] objtool: Optimize read_sections() Peter Zijlstra
2020-03-25 12:10   ` Miroslav Benes
2020-03-26 10:08   ` [tip: core/objtool] " tip-bot2 for Peter Zijlstra
2020-04-21 14:47   ` [PATCH v3 14/26] " youling257
2020-04-21 15:49     ` Peter Zijlstra
2020-04-21 15:57       ` Borislav Petkov
2020-04-21 17:50       ` youling 257
2020-03-24 15:31 ` [PATCH v3 15/26] objtool: Delete cleanup() Peter Zijlstra
2020-03-25 12:11   ` Miroslav Benes
2020-03-26 10:08   ` [tip: core/objtool] " tip-bot2 for Peter Zijlstra
2020-03-24 15:31 ` [PATCH v3 16/26] objtool: Optimize find_rela_by_dest_range() Peter Zijlstra
2020-03-25 12:19   ` Miroslav Benes
2020-03-26 10:08   ` [tip: core/objtool] " tip-bot2 for Peter Zijlstra
2020-03-24 15:31 ` [PATCH v3 17/26] objtool: Re-arrange validate_functions() Peter Zijlstra
2020-03-24 21:10   ` Josh Poimboeuf
2020-03-24 21:15     ` Peter Zijlstra
2020-03-25 12:22   ` Miroslav Benes
2020-03-26 10:08   ` [tip: core/objtool] " tip-bot2 for Peter Zijlstra
2020-03-24 15:31 ` [PATCH v3 18/26] objtool: Fix !CFI insn_state propagation Peter Zijlstra
2020-03-24 21:40   ` Josh Poimboeuf
2020-03-24 22:11     ` Peter Zijlstra
2020-03-24 23:00       ` Peter Zijlstra
2020-03-25 14:39         ` Josh Poimboeuf
2020-03-25 14:41   ` [PATCH v3.1 18a/26] objtool: Remove CFI save/restore special case Peter Zijlstra
2020-03-25 14:42   ` [PATCH v3.1 18b/26] objtool: Factor out CFI hints Peter Zijlstra
2020-03-25 14:43   ` [PATCH v3.1 18c/26] objtool: Rename struct cfi_state Peter Zijlstra
2020-03-25 14:43   ` [PATCH v3.1 18d/26] objtool: Fix !CFI insn_state propagation Peter Zijlstra
2020-03-24 15:31 ` [PATCH v3 19/26] objtool: Implement noinstr validation Peter Zijlstra
2020-03-24 21:41   ` Josh Poimboeuf
2020-03-25 14:44   ` [PATCH v3.1 " Peter Zijlstra
2020-03-24 15:31 ` Peter Zijlstra [this message]
2020-03-24 15:31 ` [PATCH v3 21/26] objtool: Use sec_offset_hash() for insn_hash Peter Zijlstra
2020-03-24 15:31 ` [PATCH v3 22/26] objtool: Detect loading function pointers across noinstr Peter Zijlstra
2020-03-24 15:31 ` [PATCH v3 23/26] kbuild/objtool: Add objtool-vmlinux.o pass Peter Zijlstra
2020-03-24 22:03   ` Josh Poimboeuf
2020-03-24 22:05     ` Peter Zijlstra
2020-03-24 15:31 ` [PATCH v3 24/26] objtool: Avoid iterating !text section symbols Peter Zijlstra
2020-03-24 22:09   ` Josh Poimboeuf
2020-03-24 15:31 ` [PATCH v3 25/26] objtool: Rearrange validate_section() Peter Zijlstra
2020-03-24 22:10   ` Josh Poimboeuf
2020-03-24 15:31 ` [PATCH v3 26/26] objtool: Add STT_NOTYPE noinstr validation Peter Zijlstra
2020-03-24 22:16   ` Josh Poimboeuf
2020-03-24 22:34     ` Peter Zijlstra
2020-03-25 14:42       ` Josh Poimboeuf
2020-03-25 15:53         ` Peter Zijlstra
2020-03-25 16:40           ` Josh Poimboeuf
2020-03-25 16:50             ` Peter Zijlstra
2020-03-26  8:01               ` Julien Thierry

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200324160925.107835416@infradead.org \
    --to=peterz@infradead.org \
    --cc=brgerst@gmail.com \
    --cc=jpoimboe@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mbenes@suse.cz \
    --cc=mhiramat@kernel.org \
    --cc=tglx@linutronix.de \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.