On Thu, 3 Oct 2024, Jason Merrill wrote:

> On 10/2/24 7:53 AM, Richard Biener wrote:
> > For a specific testcase a lot of compile-time is spent in re-hashing
> > hashtable elements upon expansion.  The following records the hash
> > in the hash element.  This speeds up compilation by 20%.
> > 
> > There's probably module-related uses that need to be adjusted.
> > 
> > Bootstrap failed (guess I was expecting this), but still I think this
> > is a good idea - maybe somebody can pick it up.
> 
> Applying the attached, thanks!
> 
> > Possibly instead of having a single global hash table having one per ID
> > would be
> > better.
> 
> That sounds excessive to me.  Is the actual hashtable lookup significant in
> the profile?

No, it's still template hashing at the top.

> > The hashtable also keeps things GC-live ('args' for example).
> 
> Those args should also be referenced by TI_ARGS from the respective template
> specialization.

I see.  The changes improved things, the biggest fruit we can possibly
still reap is coerce_template_parameter_pack causing 6GB transitional
garbage we could release earlier (the packed_args allocation at the
start of the function, the testcase ticks the last one,
packed_args = make_tree_vec (nargs - arg_idx)).

I've pasted the testcase below - it looks innocous and I suspect
filling the templates with actual "meat" would shift the blame from
argument/type vectors to elsewhere?

clang++-17 just blew past my little machines 32GB of memory so at least
we're not worst here.

Richard.



template <typename T, typename U>
  struct Add
  {};

template <typename...>
  struct Operand
  {};

template <typename... Ts, typename... Us>
  Operand<Ts..., Us...>
  operator+(const Operand<Ts...>&, const Operand<Us...>&)
  { return {}; }

auto
stress_me(auto x)
{
  return (x + x) + x + (x + (x + x) + x) + x + x;
}

auto
apply_stress(auto op)
{
  return stress_me(stress_me(stress_me(stress_me(stress_me(op)))));
}


template <typename... Ts>
  struct typelist
  {};

void
invoke(auto);

template <typename T0, typename... Ts>
  void
  apply(typelist<T0, Ts...>, auto&& fun)
  {
    fun(T0{});
    if constexpr (sizeof...(Ts))
      apply(typelist<Ts...>(), fun);
  }


template <typename T>
  Operand<T>
  make_operand(T)
  { return {}; }

auto
pah()
{

  apply(typelist<char, signed char, unsigned char, wchar_t, char8_t, char16_t, 
char32_t,
                 short, unsigned short, int, unsigned, long, unsigned long, 
long long,
                 unsigned long long, float, double, long double, bool>(),
        [](auto op) {
          apply(typelist<char, signed char, unsigned char, wchar_t, char8_t, 
char16_t, char32_t,
                         short, unsigned short, int, unsigned, long, unsigned 
long, long long,
                         unsigned long long, float, double, long double, 
bool>(),
                [&op](auto op2) {
                  invoke(apply_stress(make_operand(op) + make_operand(op2)));
                });
        });



}

Reply via email to