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))); }); }); }