PR32260: Improve estimate of number of strings

Michael Matz matz@suse.de
Thu Oct 17 13:28:58 GMT 2024


Hello,

On Thu, 17 Oct 2024, Alan Modra wrote:

> > 	bfd/
> > 
> > 	PR ld/32260
> > 	* merge.c (record_section): Throttle down the overestimation
> > 	of number of entries in a section.
> 
> So this does cut down the estimate, but I think it's still wildly
> oversize to use an upper bound here.

Yes, it's complete bollocks^W^Wvery very conservative.  

> You're calculating for an input section of unique strings (8-bit too, 
> not 7-bit).  How often is that going to happen in real object files?

Mostly never, of course.  Except in constructed examples that would try to 
trigger this by enumerating all 5-character strings for instance. I 
wanted to get it 100% correct in these cases as well, first, and then see 
how bad it is in practice (on the grounds that the terrible 
over-estimation will usually be used up by further mergable blobs).  
Turns out that it seems to be mostly okay, except in these insane cases 
like in the bug report :-)

So, yeah, I think I'll try to do something more fancy.  There are 
probalistic measures about how many unique things will most likely be 
contained in blobs, and suchlike.  Thing is: when I wrote all that code 
there was really a non-negligible performance impact when trying to do the 
resizing on demand in the hot loop instead of ensuring its not necessary.  

> The other thing that occurs to me is that the merge.c code doesn't
> avoid resizing sinfo->htab.  Can't we delay creation of sinfo->htab
> until _bfd_merge_sections,

Delaying the creation itself doesn't matter much, the resizing and real 
large allocations already happen only from within record_section and 
hence _bfd_merge_sections ...

> and then make a better estimate of the size
> required from the total size of sections that will be added to the
> hash table?

... but this is possible.  If there's better estimate of course.  Right 
now it conceptually works like this:

  for all input-sections S:
    estimate = foo(S.size);
    resize (estimate);
    do_stuff_without_resizing(S);  // 1

At (1) the potential overestimations from earlier S's will be used up.  If 
we were to instead resize the htab to be completely outside the loop over 
the input blobs:

  foreach S:
    wholesize += S.size;
  resize (estimate (wholesize));
  foreach S:
    do_stuff_without_resizing(S);

then there is no opportunity anymore to use up earlier over-estimates, as 
there's just a single measurement.  So the estimate() really needs to be 
good now, and doing that without reading and interpreting S's contents is hard.

I can see only one way here: do a less conservative estimate, and then 
live with the fact that there needs to be a needs-resize check in the hot 
loop.

> If you used your upper bound then you'd need no resizing.
> 
> Perhaps even better would be to use a more conservative estimate
> based on the total section size, then implement resizing in the normal
> fashion on inserting entries.

You mean "less conservative", right?  In the sense of less over-estimation 
and hence not all content fitting into the table.

Anyway, I'll try to rewrite the code a little and see how the performance 
fares.


Ciao,
Michael.


More information about the Binutils mailing list