.gdb_index prod perf regression: Estimate size of psyms_seen

Using the same test as the previous patch, perf shows GDB spending
over 7% in "free".  A substantial number of those calls comes from
insertions in the psyms_seen unordered_set causing lots of rehashing
and recreating buckets.  Fix this by computing an estimate of the size
of the set upfront.

Using the same test as in the previous patch, against the same gdb
inferior, timing improves ~8% further:

  ~6.5s => ~6.0s (average of 5 runs).

gdb/ChangeLog:
2017-06-12  Pedro Alves  <palves@redhat.com>

	* dwarf2read.c (recursively_count_psymbols): New function.
	(write_psymtabs_to_index): Call it to compute number of psyms and
	pass estimate size of psyms_seen to unordered_set's ctor.
This commit is contained in:
Pedro Alves 2017-06-12 02:40:18 +01:00
parent 70a1152bee
commit e8f8bcb35f
2 changed files with 41 additions and 1 deletions

View File

@ -1,3 +1,9 @@
2017-06-12 Pedro Alves <palves@redhat.com>
* dwarf2read.c (recursively_count_psymbols): New function.
(write_psymtabs_to_index): Call it to compute number of psyms and
pass estimate size of psyms_seen to unordered_set's ctor.
2017-06-12 Pedro Alves <palves@redhat.com>
* dwarf2read.c (write_hash_table): Check if key already exists

View File

@ -23691,6 +23691,22 @@ write_one_signatured_type (void **slot, void *d)
return 1;
}
/* Recurse into all "included" dependencies and count their symbols as
if they appeared in this psymtab. */
static void
recursively_count_psymbols (struct partial_symtab *psymtab,
size_t &psyms_seen)
{
for (int i = 0; i < psymtab->number_of_dependencies; ++i)
if (psymtab->dependencies[i]->user != NULL)
recursively_count_psymbols (psymtab->dependencies[i],
psyms_seen);
psyms_seen += psymtab->n_global_syms;
psyms_seen += psymtab->n_static_syms;
}
/* Recurse into all "included" dependencies and write their symbols as
if they appeared in this psymtab. */
@ -23764,7 +23780,6 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir)
mapped_symtab symtab;
data_buf cu_list;
std::unordered_set<partial_symbol *> psyms_seen;
/* While we're scanning CU's create a table that maps a psymtab pointer
(which is what addrmap records) to its index (which is what is recorded
@ -23776,6 +23791,25 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir)
/* The CU list is already sorted, so we don't need to do additional
work here. Also, the debug_types entries do not appear in
all_comp_units, but only in their own hash table. */
/* The psyms_seen set is potentially going to be largish (~40k
elements when indexing a -g3 build of GDB itself). Estimate the
number of elements in order to avoid too many rehashes, which
require rebuilding buckets and thus many trips to
malloc/free. */
size_t psyms_count = 0;
for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
{
struct dwarf2_per_cu_data *per_cu
= dwarf2_per_objfile->all_comp_units[i];
struct partial_symtab *psymtab = per_cu->v.psymtab;
if (psymtab != NULL && psymtab->user == NULL)
recursively_count_psymbols (psymtab, psyms_count);
}
/* Generating an index for gdb itself shows a ratio of
TOTAL_SEEN_SYMS/UNIQUE_SYMS or ~5. 4 seems like a good bet. */
std::unordered_set<partial_symbol *> psyms_seen (psyms_count / 4);
for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
{
struct dwarf2_per_cu_data *per_cu