Skip to content

Internal stdexec instantiation dominating compilation time -- any room for optimization? #1719

@vittorioromeo

Description

@vittorioromeo

Hello! We heavily use stdexec in one of our projects, which unfortunately is taking longer and longer to compile as we add more functionality.

I've run a trace using ClangBuildAnalyzer on our project, and the compilation time is dominated by internal instantiations of stdexec templates:

**** Template sets that took longest to instantiate:
696601 ms: stdexec::__sigs::get_completion_signatures_t::__impl<stdexec::(anony... (11136 times, avg 62 ms)
627460 ms: stdexec::__sigs::get_completion_signatures_t::__impl<stdexec::(anony... (12135 times, avg 51 ms)
589798 ms: stdexec::dependent_domain::transform_sender<stdexec::(anonymous name... (4923 times, avg 119 ms)
585881 ms: stdexec::dependent_domain::__is_nothrow_transform_sender<stdexec::(a... (4923 times, avg 119 ms)
456104 ms: stdexec::__sigs::get_completion_signatures_t::__impl<stdexec::(anony... (8388 times, avg 54 ms)
427458 ms: stdexec::__detail::__transform_sender::operator()<stdexec::__detail:... (7188 times, avg 59 ms)
421909 ms: stdexec::__detail::__transform_sender_1::operator()<stdexec::depende... (7032 times, avg 59 ms)
421252 ms: stdexec::__detail::__transform_sender_1::__is_nothrow<stdexec::depen... (6930 times, avg 60 ms)
414298 ms: stdexec::__sigs::get_completion_signatures_t::__impl<stdexec::(anony... (9252 times, avg 44 ms)
406173 ms: stdexec::dependent_domain::transform_sender<stdexec::(anonymous name... (3942 times, avg 103 ms)
403291 ms: stdexec::dependent_domain::__is_nothrow_transform_sender<stdexec::(a... (3942 times, avg 102 ms)
360123 ms: stdexec::dependent_domain::transform_sender<stdexec::(anonymous name... (4923 times, avg 73 ms)
356306 ms: stdexec::dependent_domain::__is_nothrow_transform_sender<stdexec::(a... (4923 times, avg 72 ms)
294444 ms: stdexec::__detail::__transform_sender::operator()<stdexec::__detail:... (5754 times, avg 51 ms)
290450 ms: stdexec::__detail::__transform_sender_1::operator()<stdexec::depende... (5631 times, avg 51 ms)
289950 ms: stdexec::__detail::__transform_sender_1::__is_nothrow<stdexec::depen... (5544 times, avg 52 ms)
258438 ms: stdexec::__detail::__transform_sender::operator()<stdexec::__detail:... (3960 times, avg 65 ms)
256370 ms: stdexec::__detail::__transform_sender_1::operator()<stdexec::depende... (3543 times, avg 72 ms)
256090 ms: stdexec::__detail::__transform_sender_1::__is_nothrow<stdexec::depen... (3522 times, avg 72 ms)
235384 ms: stdexec::dependent_domain::transform_sender<stdexec::(anonymous name... (3942 times, avg 59 ms)
232346 ms: stdexec::dependent_domain::__is_nothrow_transform_sender<stdexec::(a... (3942 times, avg 58 ms)
212618 ms: stdexec::__sigs::get_completion_signatures_t::__impl<stdexec::(anony... (5829 times, avg 36 ms)
184241 ms: stdexec::__sigs::get_completion_signatures_t::__impl<exec::__scope::... (942 times, avg 195 ms)
172626 ms: stdexec::__detail::__transform_dependent_sender::operator()<stdexec:... (1413 times, avg 122 ms)
171259 ms: stdexec::dependent_domain::__is_nothrow_transform_sender()::(anonymo... (1404 times, avg 121 ms)
168674 ms: stdexec::__detail::__transform_sender::operator()<stdexec::__detail:... (3105 times, avg 54 ms)
167214 ms: stdexec::__detail::__transform_sender_1::operator()<stdexec::depende... (2823 times, avg 59 ms)

I've also ran ClangBuildAnalyzer on stdexec's test suite. Here are the results:

**** Template sets that took longest to instantiate:
 52891 ms: stdexec::__connect::connect_t::__get_declfn<$> (1002 times, avg 52 ms)
 45473 ms: stdexec::__sigs::get_completion_signatures_t::__get_declfn<$> (2660 times, avg 17 ms)
 28993 ms: std::vformat_to<$> (206 times, avg 140 ms)
 28956 ms: std::__format::__do_vformat_to<$> (205 times, avg 141 ms)
 20063 ms: std::formatter<$>::format<$> (2530 times, avg 7 ms)
 17154 ms: stdexec::default_domain::apply_sender<$> (290 times, avg 59 ms)
 13637 ms: stdexec::__queries::get_completion_domain_t<$>::__get_domain<$> (2998 times, avg 4 ms)
 13535 ms: stdexec::__get_submit_result_kind<$> (467 times, avg 28 ms)
 12269 ms: stdexec::__detail::__transform_sender_t<$>::__get_declfn<$> (1537 times, avg 7 ms)
 10940 ms: stdexec::__sync_wait::sync_wait_t::operator()<stdexec::(anonymous na... (126 times, avg 86 ms)
 10507 ms: stdexec::__let::__let_state<$> (504 times, avg 20 ms)  9639 ms: stdexec::__start_detached::start_detached_t::apply_sender<$> (32 times, avg 301 ms)
  8330 ms: stdexec::__op_state<$>::__complete<$> (1254 times, avg 6 ms)
  7977 ms: stdexec::__op_state<$>::start (701 times, avg 11 ms)
  7940 ms: stdexec::(anonymous namespace)::__sexpr<$>::static_connect<$> (826 times, avg 9 ms)
  7867 ms: std::__format::__formatter_int<$>::format<$> (1428 times, avg 5 ms)
  7802 ms: stdexec::__queries::get_completion_scheduler_t<$>::__get_declfn<$> (3840 times, avg 2 ms)
  7566 ms: stdexec::__op_state<$>::__op_state (821 times, avg 9 ms)
  7515 ms: exec::__sequence_sndr::subscribe_t::__get_declfn<$> (43 times, avg 174 ms)
  7429 ms: stdexec::__rcvr<$>::__t::set_value<$> (956 times, avg 7 ms)
  7375 ms: stdexec::__sync_wait::sync_wait_t::apply_sender<$> (254 times, avg 29 ms)
  7251 ms: stdexec::(anonymous namespace)::__sexpr<$>::apply<$> (734 times, avg 9 ms)  6843 ms: exec::__ignore_all_values::__operation<$>::__t (35 times, avg 195 ms)
  6579 ms: exec::__transform_each::__operation<$>::__t (24 times, avg 274 ms)  6378 ms: (anonymous namespace)::wait_for_value<$> (48 times, avg 132 ms)  5766 ms: stdexec::__sync_wait::sync_wait_t::operator()<stdexec::(anonymous na... (7 times, avg 823 ms)
  5574 ms: std::__format::__formatter_str<$>::format<$> (204 times, avg 27 ms)
  5343 ms: stdexec::__op_state<$> (5073 times, avg 1 ms)
  5282 ms: stdexec::__trnsfr::__state<$>::__state (756 times, avg 6 ms)  5182 ms: std::__and_<$> (5371 times, avg 0 ms)

The full report is available here on a gist.

Have these function been already heavily optimized for compilation times? It would be great to liberally use stdexec without having to worry about harming our developer velocity/productivity.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions