diesel
diesel copied to clipboard
Joins `typeck` is exponential in number of joins
Setup
Versions
- Rust: rustc 1.64.0-nightly (7665c3543 2022-07-06)
-
Diesel: 2.0.0-rc.0, features
postgres
,64-column-tables
- Operating System: Linux
Problem Description
Joins typeck
appears to be exponential in number of joins, despite incremental compilation and not touching the function that contains the joins itself.
That makes getting compiler feedback after touching a crate that uses a lot of Diesel queries take an unreasonable amount of time.
E.g. with just 7 joins:
=> With a few hundred such functions in a crate, getting the smallest amount of feedback from a cargo check when making changes easily takes several minutes.
Steps to reproduce
The following repository gives code and detailed step-by-step on how to observe this behavior: https://github.com/Ten0/diesel_3223_repro
@lqd It seems you have been investigating a similar performance issue that notably affected Diesel earlier this year. Would you have any insight on what would be the process to follow in order to tackle this? Thanks a lot! 🥰
Maybe related: https://github.com/rust-lang/rust/issues/20304
It could also be related to https://github.com/rust-lang/rust/issues/99188 which also has exponential behavior (if associated types, and big wrapped items are involved, which I'm not sure is the case here I haven't had the time to look at the repo yet).
what would be the process to follow in order to tackle this
First, it's easier if the reproduction code is minimal. That is, if it doesn't depend on diesel itself, but extracts some of the code that triggers the issue. Then trying to reduce that to a very small size, so that any other piece of code that is not related to the issue doesn't interfere with the measurement or fixing processes.
With that done (it could be done independently of course), one could also easily see if this is a new issue, or an old one, to see if it's a regression or not, and locate the PR that caused it if that's the case. Notifying the PR author and reviewer would then be good, if it is a regression.
In parallel, the easiest first step would be to narrow down the vague area of rustc where the issue happens. One would that looking at the -Zself-profile data. I would guess that either evaluate_obligation
or specialization_graph_of
would be the likeliest of queries taking a long time in this situation.
These 2 steps would also allow looking for rust issues that could already track the problem, maybe there are workarounds there, or a lack of data that prevents people from working on it. Though, if it's a stress test that doesn't look like real code people use, it may not be seen as high priority: the scalability behavior at higher Ns, while annoying and a bug needing to be fixed, can be pretty rare to hit in practice (and a sign to "not do that and hopefully have a different design if at all possible").
There are many issues filed already, and sometimes they conflict with each other: a bunch of such regressions happened because of incorrect handling for incremental compilation, and slower compile times in rare cases are a compromise compared to having possible soundness issues. A lot have been fixed already (for example, #99188 was also impacted by some trait system caching removal in 1.56 to fix incremental compilation soundness issues, there was a 1000x slowdown in that stress test. Until some of that was improved in 1.59 and performance is now better than in 1.55) and more will be in the future. But some of those are very hard to fix, and there are not many people with the time and knowledge to do so (and most of them are volunteer contributors with limited time).
All the above will help gather data to have all the information to understand the issue, and help people who could fix it.
Thanks a lot for your answer!
It could also be related to rust-lang/rust#99188 which also has exponential behavior (if associated types, and big wrapped items are involved, which I'm not sure is the case here I haven't had the time to look at the repo yet).
I looked into this yesterday as it seemed to be a very close issue (this here is indeed is an issue when evaluating a trait bound on a large wrapped type) but I think that is not the exact same issue because:
replacing the for<'x> T: Trait<'x, ... with T: Trait<'static, ... removes the exponential slowdown
(https://github.com/rust-lang/rust/issues/99188#issue-1302445774)
and everything is 'static
in our case.
Also according to this writeup the error from 99188 happens at the borrow checking step, while this one happens at the type_check_crate
step.
looking at the -Zself-profile data
So I had done that (screenshots from the reproduction repository linked above) and evaluate_obligation
seems to be a good part of what takes an unreasonable amount of time indeed, although half of the time appears to be spent in typeck
itself.
evaluate_obligation
's parameters (-Zself-profile-events=default,args
) are to evaluate whether the super long type that represents the sequence of joins satisfies QuerySource
. That notably depends on whether the contained joins satisfy QuerySource
themselves.
one could also easily see if this is a new issue, or an old one
Would that be going through https://github.com/rust-lang/rust/issues?q=is%3Aopen+label%3AI-compiletime+label%3AA-traits and looking for similarities or is there another method? (or is "one" somebody specifically? ^^)
Thanks again!
I've tried to create a minimal reproducible example without diesel here, but I failed. The example compiles, but does not reproduce the exponential behaviour. I post it nevertheless here, maybe that's helpful anyway.
I suggest:
- making a reproduction without diesel by using automatic reduction tools, starting from the repro with e.g. rust-reduce, perses, and similar tools, since it seems manually building it up from scratch is very difficult.
- trying to see if it's a regression: manually look back at old releases. If that's the case, use cargo-bisect-rust to locate the nightly and PR.
- if not, looking at open issues, not necessarily going through that exact filtering combination (even though it's possible there's one): they're not always tagged with I-compiletime or A-traits. If there is none, open a new issue with the self-contained repro. Ping the types team on the issue, and/or discuss it on their dedicated zulip stream.
- with the queries & arguments you've looked at, the next step would be to understand the part of rustc that's causing the issue, seeing if it's easy to fix or not via debugging, adding logging, bisecting the code, etc: this is not necessarily something you would have to do, but anyone wanting to fix the issue would need to. Such an issue is likely hard to debug/fix, but you never know.
I've tried to just reproduce @Ten0 results locally and I've failed doing that. So here is what I done so far:
- Modify the linked repo to include up to 17 tables. The linked table cites ~6s for typeck for this. I've observed clean build times (
cargo clean -p compile_time_test
+cargo check
) for the affected crate of ~8s, so that seems to fit - Now if I just modify the other function, that does not touch the joins I get check times of less than a second, if I modify the joins (even just whitespace changes there) I get check times of ~ 8-9s, which are in line with the results above.
That means at least for me the check times are heavily dependent on what is cached by incremental compilation and what not.
(This happens with the latest nightly as well as the referenced compiler version)
- Now if I just modify the other function
Incremental compilation cache is actually pretty smart here: if you modify the value in the println, or the value of a number, etc, it will actually hit the cache and not recheck the whole crate. Have you done the comment/uncomment stuff and added a new println for each measured run? (steps 2 and 6) In my case this little amount of changes - actually adding instructions - is necessary to trigger the issue. (It's also something that happens all the time in regular coding so the compiler being smart in this case doesn't help that much with the original issue)
Incremental compilation cache is actually pretty smart here: if you modify the value in the println, or the value of a number, etc, it will actually hit the cache and not recheck the whole crate. Have you done the comment/uncomment stuff and added a new println for each measured run? (steps 2 and 6) In my case this little amount of changes - actually adding instructions - is necessary to trigger the issue. (It's also something that happens all the time in regular coding so the compiler being smart in this case doesn't help that much with the original issue)
I should have been more precise about this. The following changes do not result in a large check time:
- Commenting in/out a single
println!
indifferent_each_regen
- Commenting in/out the whole
different_each_regen
function
The following changes do result in large check times:
- Adding/removing a
println!
statement todifferent_each_regen
- Adding any empty line before the
body_0
function - Changing some whitespace inside the
body_0
function
I assume that all of the later changes just invalidate the incremental compilation cache.
In my opinion that gives two issues to maybe report to the rustc team:
- Caching should not be dependent on unrelated changes, especially adding stuff into some function before should not invalid a cache entry at all in my eyes.
- Typeck being slow for this case, although that likely needs a minimal example.
Caching should not be dependent on unrelated changes, especially adding stuff into some function before should not invalid a cache entry at all in my eyes
This is a known issue and is being worked on: adding things above a function currently changes the spans of all the items following it, invalidating them since they can be used to refer to other items' locations in diagnostics for example.
It could be interesting to try the WIP work supposed to fix some of these cases: -Zincremental-relative-spans
, although IIRC it currently still pessimizes diesel, so it's both not ready yet and may not change anything here 😓.
The following changes do result in large check times: * Adding/removing a
println!
statement todifferent_each_regen
So it looks like you did succeed to reproduce my results. :)
-Zincremental-relative-spans
Indeed doesn't change anything for this particular reproduction case.
adding things above a function currently changes the spans of all the items following it, invalidating them since they can be used to refer to other items' locations in diagnostics for example
It looks like I failed to correctly extract the repro from my original crate then:
- Here when I update a module, only the functions below it are rechecked and take tons of time.
- In my original crate I can see all the functions being rechecked and taking that unreasonable amount of time upon typecheck, not only those whose position in a given file have changed.
Any clue of why that could be? That would probably help me to extract another example.
Thanks for this information. It's good to hear that this is already worked on.
I've run some more profiling on this. Everything that follows is with 17 tables + recorded with -Z self-profile -Z self-profile-events=default,args
- Summarize says that it is spending 6.2s out of 8s in
evaluate_obligation
(so 74% of the time is spend there) - Exporting the profile into the chrome profile viewer shows the following trace:
- There are growing blocks of 5 calls to
evaluate_obligation
- (See below for the arguments of the largest blocks)
- Times for the largest block are: 60ms, 320ms, 32ms, 412ms, 376ms, which does not look to bad in my easy considering the types involved.
- Problem seems to be that these 5 segment blocks build up for different sizes. It repeats over and over again, trying to prove essentially the same bounds I would guess
- I guess that these blocks corresponds to the following trait bounds/impls in diesel:
- First block:
some_table1::table: JoinTo<Rhs>
- Second block:
Rhs: QuerySource
- Third block:
On: AppearsOnTable<Join>
- Fourth block:
Left::Output: SelectableExpression<Join<…>>
- Fifth block:
Join::DefaultSelection: SelectableExpression<JoinOn<…>>
- First block:
- There are growing blocks of 5 calls to
It's not clear for my why exatly this bounds show up as beeing that expensive to evaluate, while other bounds seems to be fine even if they involve similar types.
First `evaluate_obligation` in a block
This one takes 60msarg0:
Canonical { max_universe: U0, variables: [], value: ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing, constness: NotConst }, value: Binder(TraitPredicate(<compile_time_test_schema::some_table_1::table as diesel::JoinTo<diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_2::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_3::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_4::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_5::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_6::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_7::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_8::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_9::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_10::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_11::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_12::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_13::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_14::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_15::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_16::table, compile_time_test_schema::some_table_17::table, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_16::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_17::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_15::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_16::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_14::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_15::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_13::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_14::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_12::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_13::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_11::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_12::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_10::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_11::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_9::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_10::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_8::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_9::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_7::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_8::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_6::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_7::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_5::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_6::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_4::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_5::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_3::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_4::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_2::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_3::id>>>>>>>>, polarity:Positive), []) } }
Second `evaluate_obligation` in a block
This one takes 320msarg0:
"Canonical { max_universe: U0, variables: [], value: ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing, constness: NotConst }, value: Binder(TraitPredicate(<diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_2::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_3::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_4::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_5::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_6::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_7::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_8::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_9::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_10::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_11::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_12::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_13::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_14::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_15::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_16::table, compile_time_test_schema::some_table_17::table, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_16::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_17::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_15::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_16::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_14::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_15::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_13::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_14::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_12::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_13::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_11::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_12::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_10::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_11::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_9::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_10::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_8::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_9::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_7::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_8::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_6::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_7::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_5::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_6::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_4::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_5::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_3::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_4::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_2::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_3::id>>>>>> as diesel::QuerySource>, polarity:Positive), []) } }"
Third `evaluate_obligation` in a block
This one takes 32ms
arg0:
"Canonical { max_universe: U0, variables: [], value: ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing, constness: NotConst }, value: Binder(TraitPredicate(<diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_1::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_2::id>>> as diesel::AppearsOnTable<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_1::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_2::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_3::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_4::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_5::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_6::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_7::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_8::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_9::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_10::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_11::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_12::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_13::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_14::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_15::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_16::table, compile_time_test_schema::some_table_17::table, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_16::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_17::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_15::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_16::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_14::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_15::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_13::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_14::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_12::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_13::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_11::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_12::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_10::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_11::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_9::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_10::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_8::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_9::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_7::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_8::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_6::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_7::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_5::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_6::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_4::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_5::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_3::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_4::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_2::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_3::id>>>>>>, diesel::internal::table_macro::Inner>>>, polarity:Positive), []) } }"
Fourth `evaluate_obligation` in a block
This one takes 412ms
arg0:
"Canonical { max_universe: U0, variables: [], value: ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing, constness: NotConst }, value: Binder(TraitPredicate(<((compile_time_test_schema::some_table_2::id, compile_time_test_schema::some_table_2::field_0, compile_time_test_schema::some_table_2::field_1, compile_time_test_schema::some_table_2::field_2, compile_time_test_schema::some_table_2::field_3, compile_time_test_schema::some_table_2::field_4, compile_time_test_schema::some_table_2::field_5, compile_time_test_schema::some_table_2::field_6, compile_time_test_schema::some_table_2::field_7, compile_time_test_schema::some_table_2::field_8, compile_time_test_schema::some_table_2::field_9), ((compile_time_test_schema::some_table_3::id, compile_time_test_schema::some_table_3::field_0, compile_time_test_schema::some_table_3::field_1, compile_time_test_schema::some_table_3::field_2, compile_time_test_schema::some_table_3::field_3, compile_time_test_schema::some_table_3::field_4, compile_time_test_schema::some_table_3::field_5, compile_time_test_schema::some_table_3::field_6, compile_time_test_schema::some_table_3::field_7, compile_time_test_schema::some_table_3::field_8, compile_time_test_schema::some_table_3::field_9), ((compile_time_test_schema::some_table_4::id, compile_time_test_schema::some_table_4::field_0, compile_time_test_schema::some_table_4::field_1, compile_time_test_schema::some_table_4::field_2, compile_time_test_schema::some_table_4::field_3, compile_time_test_schema::some_table_4::field_4, compile_time_test_schema::some_table_4::field_5, compile_time_test_schema::some_table_4::field_6, compile_time_test_schema::some_table_4::field_7, compile_time_test_schema::some_table_4::field_8, compile_time_test_schema::some_table_4::field_9), ((compile_time_test_schema::some_table_5::id, compile_time_test_schema::some_table_5::field_0, compile_time_test_schema::some_table_5::field_1, compile_time_test_schema::some_table_5::field_2, compile_time_test_schema::some_table_5::field_3, compile_time_test_schema::some_table_5::field_4, compile_time_test_schema::some_table_5::field_5, compile_time_test_schema::some_table_5::field_6, compile_time_test_schema::some_table_5::field_7, compile_time_test_schema::some_table_5::field_8, compile_time_test_schema::some_table_5::field_9), ((compile_time_test_schema::some_table_6::id, compile_time_test_schema::some_table_6::field_0, compile_time_test_schema::some_table_6::field_1, compile_time_test_schema::some_table_6::field_2, compile_time_test_schema::some_table_6::field_3, compile_time_test_schema::some_table_6::field_4, compile_time_test_schema::some_table_6::field_5, compile_time_test_schema::some_table_6::field_6, compile_time_test_schema::some_table_6::field_7, compile_time_test_schema::some_table_6::field_8, compile_time_test_schema::some_table_6::field_9), ((compile_time_test_schema::some_table_7::id, compile_time_test_schema::some_table_7::field_0, compile_time_test_schema::some_table_7::field_1, compile_time_test_schema::some_table_7::field_2, compile_time_test_schema::some_table_7::field_3, compile_time_test_schema::some_table_7::field_4, compile_time_test_schema::some_table_7::field_5, compile_time_test_schema::some_table_7::field_6, compile_time_test_schema::some_table_7::field_7, compile_time_test_schema::some_table_7::field_8, compile_time_test_schema::some_table_7::field_9), ((compile_time_test_schema::some_table_8::id, compile_time_test_schema::some_table_8::field_0, compile_time_test_schema::some_table_8::field_1, compile_time_test_schema::some_table_8::field_2, compile_time_test_schema::some_table_8::field_3, compile_time_test_schema::some_table_8::field_4, compile_time_test_schema::some_table_8::field_5, compile_time_test_schema::some_table_8::field_6, compile_time_test_schema::some_table_8::field_7, compile_time_test_schema::some_table_8::field_8, compile_time_test_schema::some_table_8::field_9), ((compile_time_test_schema::some_table_9::id, compile_time_test_schema::some_table_9::field_0, compile_time_test_schema::some_table_9::field_1, compile_time_test_schema::some_table_9::field_2, compile_time_test_schema::some_table_9::field_3, compile_time_test_schema::some_table_9::field_4, compile_time_test_schema::some_table_9::field_5, compile_time_test_schema::some_table_9::field_6, compile_time_test_schema::some_table_9::field_7, compile_time_test_schema::some_table_9::field_8, compile_time_test_schema::some_table_9::field_9), ((compile_time_test_schema::some_table_10::id, compile_time_test_schema::some_table_10::field_0, compile_time_test_schema::some_table_10::field_1, compile_time_test_schema::some_table_10::field_2, compile_time_test_schema::some_table_10::field_3, compile_time_test_schema::some_table_10::field_4, compile_time_test_schema::some_table_10::field_5, compile_time_test_schema::some_table_10::field_6, compile_time_test_schema::some_table_10::field_7, compile_time_test_schema::some_table_10::field_8, compile_time_test_schema::some_table_10::field_9), ((compile_time_test_schema::some_table_11::id, compile_time_test_schema::some_table_11::field_0, compile_time_test_schema::some_table_11::field_1, compile_time_test_schema::some_table_11::field_2, compile_time_test_schema::some_table_11::field_3, compile_time_test_schema::some_table_11::field_4, compile_time_test_schema::some_table_11::field_5, compile_time_test_schema::some_table_11::field_6, compile_time_test_schema::some_table_11::field_7, compile_time_test_schema::some_table_11::field_8, compile_time_test_schema::some_table_11::field_9), ((compile_time_test_schema::some_table_12::id, compile_time_test_schema::some_table_12::field_0, compile_time_test_schema::some_table_12::field_1, compile_time_test_schema::some_table_12::field_2, compile_time_test_schema::some_table_12::field_3, compile_time_test_schema::some_table_12::field_4, compile_time_test_schema::some_table_12::field_5, compile_time_test_schema::some_table_12::field_6, compile_time_test_schema::some_table_12::field_7, compile_time_test_schema::some_table_12::field_8, compile_time_test_schema::some_table_12::field_9), ((compile_time_test_schema::some_table_13::id, compile_time_test_schema::some_table_13::field_0, compile_time_test_schema::some_table_13::field_1, compile_time_test_schema::some_table_13::field_2, compile_time_test_schema::some_table_13::field_3, compile_time_test_schema::some_table_13::field_4, compile_time_test_schema::some_table_13::field_5, compile_time_test_schema::some_table_13::field_6, compile_time_test_schema::some_table_13::field_7, compile_time_test_schema::some_table_13::field_8, compile_time_test_schema::some_table_13::field_9), ((compile_time_test_schema::some_table_14::id, compile_time_test_schema::some_table_14::field_0, compile_time_test_schema::some_table_14::field_1, compile_time_test_schema::some_table_14::field_2, compile_time_test_schema::some_table_14::field_3, compile_time_test_schema::some_table_14::field_4, compile_time_test_schema::some_table_14::field_5, compile_time_test_schema::some_table_14::field_6, compile_time_test_schema::some_table_14::field_7, compile_time_test_schema::some_table_14::field_8, compile_time_test_schema::some_table_14::field_9), ((compile_time_test_schema::some_table_15::id, compile_time_test_schema::some_table_15::field_0, compile_time_test_schema::some_table_15::field_1, compile_time_test_schema::some_table_15::field_2, compile_time_test_schema::some_table_15::field_3, compile_time_test_schema::some_table_15::field_4, compile_time_test_schema::some_table_15::field_5, compile_time_test_schema::some_table_15::field_6, compile_time_test_schema::some_table_15::field_7, compile_time_test_schema::some_table_15::field_8, compile_time_test_schema::some_table_15::field_9), ((compile_time_test_schema::some_table_16::id, compile_time_test_schema::some_table_16::field_0, compile_time_test_schema::some_table_16::field_1, compile_time_test_schema::some_table_16::field_2, compile_time_test_schema::some_table_16::field_3, compile_time_test_schema::some_table_16::field_4, compile_time_test_schema::some_table_16::field_5, compile_time_test_schema::some_table_16::field_6, compile_time_test_schema::some_table_16::field_7, compile_time_test_schema::some_table_16::field_8, compile_time_test_schema::some_table_16::field_9), (compile_time_test_schema::some_table_17::id, compile_time_test_schema::some_table_17::field_0, compile_time_test_schema::some_table_17::field_1, compile_time_test_schema::some_table_17::field_2, compile_time_test_schema::some_table_17::field_3, compile_time_test_schema::some_table_17::field_4, compile_time_test_schema::some_table_17::field_5, compile_time_test_schema::some_table_17::field_6, compile_time_test_schema::some_table_17::field_7, compile_time_test_schema::some_table_17::field_8, compile_time_test_schema::some_table_17::field_9)))))))))))))))) as diesel::SelectableExpression<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_1::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_2::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_3::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_4::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_5::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_6::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_7::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_8::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_9::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_10::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_11::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_12::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_13::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_14::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_15::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_16::table, compile_time_test_schema::some_table_17::table, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_16::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_17::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_15::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_16::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_14::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_15::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_13::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_14::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_12::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_13::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_11::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_12::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_10::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_11::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_9::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_10::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_8::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_9::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_7::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_8::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_6::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_7::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_5::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_6::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_4::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_5::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_3::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_4::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_2::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_3::id>>>>>>, diesel::internal::table_macro::Inner>>>, polarity:Positive), []) } }"
Fifth `evaluate_obligation` in a block
This one takes 376ms
arg0:
"Canonical { max_universe: U0, variables: [], value: ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing, constness: NotConst }, value: Binder(TraitPredicate(<((compile_time_test_schema::some_table_2::id, compile_time_test_schema::some_table_2::field_0, compile_time_test_schema::some_table_2::field_1, compile_time_test_schema::some_table_2::field_2, compile_time_test_schema::some_table_2::field_3, compile_time_test_schema::some_table_2::field_4, compile_time_test_schema::some_table_2::field_5, compile_time_test_schema::some_table_2::field_6, compile_time_test_schema::some_table_2::field_7, compile_time_test_schema::some_table_2::field_8, compile_time_test_schema::some_table_2::field_9), ((compile_time_test_schema::some_table_3::id, compile_time_test_schema::some_table_3::field_0, compile_time_test_schema::some_table_3::field_1, compile_time_test_schema::some_table_3::field_2, compile_time_test_schema::some_table_3::field_3, compile_time_test_schema::some_table_3::field_4, compile_time_test_schema::some_table_3::field_5, compile_time_test_schema::some_table_3::field_6, compile_time_test_schema::some_table_3::field_7, compile_time_test_schema::some_table_3::field_8, compile_time_test_schema::some_table_3::field_9), ((compile_time_test_schema::some_table_4::id, compile_time_test_schema::some_table_4::field_0, compile_time_test_schema::some_table_4::field_1, compile_time_test_schema::some_table_4::field_2, compile_time_test_schema::some_table_4::field_3, compile_time_test_schema::some_table_4::field_4, compile_time_test_schema::some_table_4::field_5, compile_time_test_schema::some_table_4::field_6, compile_time_test_schema::some_table_4::field_7, compile_time_test_schema::some_table_4::field_8, compile_time_test_schema::some_table_4::field_9), ((compile_time_test_schema::some_table_5::id, compile_time_test_schema::some_table_5::field_0, compile_time_test_schema::some_table_5::field_1, compile_time_test_schema::some_table_5::field_2, compile_time_test_schema::some_table_5::field_3, compile_time_test_schema::some_table_5::field_4, compile_time_test_schema::some_table_5::field_5, compile_time_test_schema::some_table_5::field_6, compile_time_test_schema::some_table_5::field_7, compile_time_test_schema::some_table_5::field_8, compile_time_test_schema::some_table_5::field_9), ((compile_time_test_schema::some_table_6::id, compile_time_test_schema::some_table_6::field_0, compile_time_test_schema::some_table_6::field_1, compile_time_test_schema::some_table_6::field_2, compile_time_test_schema::some_table_6::field_3, compile_time_test_schema::some_table_6::field_4, compile_time_test_schema::some_table_6::field_5, compile_time_test_schema::some_table_6::field_6, compile_time_test_schema::some_table_6::field_7, compile_time_test_schema::some_table_6::field_8, compile_time_test_schema::some_table_6::field_9), ((compile_time_test_schema::some_table_7::id, compile_time_test_schema::some_table_7::field_0, compile_time_test_schema::some_table_7::field_1, compile_time_test_schema::some_table_7::field_2, compile_time_test_schema::some_table_7::field_3, compile_time_test_schema::some_table_7::field_4, compile_time_test_schema::some_table_7::field_5, compile_time_test_schema::some_table_7::field_6, compile_time_test_schema::some_table_7::field_7, compile_time_test_schema::some_table_7::field_8, compile_time_test_schema::some_table_7::field_9), ((compile_time_test_schema::some_table_8::id, compile_time_test_schema::some_table_8::field_0, compile_time_test_schema::some_table_8::field_1, compile_time_test_schema::some_table_8::field_2, compile_time_test_schema::some_table_8::field_3, compile_time_test_schema::some_table_8::field_4, compile_time_test_schema::some_table_8::field_5, compile_time_test_schema::some_table_8::field_6, compile_time_test_schema::some_table_8::field_7, compile_time_test_schema::some_table_8::field_8, compile_time_test_schema::some_table_8::field_9), ((compile_time_test_schema::some_table_9::id, compile_time_test_schema::some_table_9::field_0, compile_time_test_schema::some_table_9::field_1, compile_time_test_schema::some_table_9::field_2, compile_time_test_schema::some_table_9::field_3, compile_time_test_schema::some_table_9::field_4, compile_time_test_schema::some_table_9::field_5, compile_time_test_schema::some_table_9::field_6, compile_time_test_schema::some_table_9::field_7, compile_time_test_schema::some_table_9::field_8, compile_time_test_schema::some_table_9::field_9), ((compile_time_test_schema::some_table_10::id, compile_time_test_schema::some_table_10::field_0, compile_time_test_schema::some_table_10::field_1, compile_time_test_schema::some_table_10::field_2, compile_time_test_schema::some_table_10::field_3, compile_time_test_schema::some_table_10::field_4, compile_time_test_schema::some_table_10::field_5, compile_time_test_schema::some_table_10::field_6, compile_time_test_schema::some_table_10::field_7, compile_time_test_schema::some_table_10::field_8, compile_time_test_schema::some_table_10::field_9), ((compile_time_test_schema::some_table_11::id, compile_time_test_schema::some_table_11::field_0, compile_time_test_schema::some_table_11::field_1, compile_time_test_schema::some_table_11::field_2, compile_time_test_schema::some_table_11::field_3, compile_time_test_schema::some_table_11::field_4, compile_time_test_schema::some_table_11::field_5, compile_time_test_schema::some_table_11::field_6, compile_time_test_schema::some_table_11::field_7, compile_time_test_schema::some_table_11::field_8, compile_time_test_schema::some_table_11::field_9), ((compile_time_test_schema::some_table_12::id, compile_time_test_schema::some_table_12::field_0, compile_time_test_schema::some_table_12::field_1, compile_time_test_schema::some_table_12::field_2, compile_time_test_schema::some_table_12::field_3, compile_time_test_schema::some_table_12::field_4, compile_time_test_schema::some_table_12::field_5, compile_time_test_schema::some_table_12::field_6, compile_time_test_schema::some_table_12::field_7, compile_time_test_schema::some_table_12::field_8, compile_time_test_schema::some_table_12::field_9), ((compile_time_test_schema::some_table_13::id, compile_time_test_schema::some_table_13::field_0, compile_time_test_schema::some_table_13::field_1, compile_time_test_schema::some_table_13::field_2, compile_time_test_schema::some_table_13::field_3, compile_time_test_schema::some_table_13::field_4, compile_time_test_schema::some_table_13::field_5, compile_time_test_schema::some_table_13::field_6, compile_time_test_schema::some_table_13::field_7, compile_time_test_schema::some_table_13::field_8, compile_time_test_schema::some_table_13::field_9), ((compile_time_test_schema::some_table_14::id, compile_time_test_schema::some_table_14::field_0, compile_time_test_schema::some_table_14::field_1, compile_time_test_schema::some_table_14::field_2, compile_time_test_schema::some_table_14::field_3, compile_time_test_schema::some_table_14::field_4, compile_time_test_schema::some_table_14::field_5, compile_time_test_schema::some_table_14::field_6, compile_time_test_schema::some_table_14::field_7, compile_time_test_schema::some_table_14::field_8, compile_time_test_schema::some_table_14::field_9), ((compile_time_test_schema::some_table_15::id, compile_time_test_schema::some_table_15::field_0, compile_time_test_schema::some_table_15::field_1, compile_time_test_schema::some_table_15::field_2, compile_time_test_schema::some_table_15::field_3, compile_time_test_schema::some_table_15::field_4, compile_time_test_schema::some_table_15::field_5, compile_time_test_schema::some_table_15::field_6, compile_time_test_schema::some_table_15::field_7, compile_time_test_schema::some_table_15::field_8, compile_time_test_schema::some_table_15::field_9), ((compile_time_test_schema::some_table_16::id, compile_time_test_schema::some_table_16::field_0, compile_time_test_schema::some_table_16::field_1, compile_time_test_schema::some_table_16::field_2, compile_time_test_schema::some_table_16::field_3, compile_time_test_schema::some_table_16::field_4, compile_time_test_schema::some_table_16::field_5, compile_time_test_schema::some_table_16::field_6, compile_time_test_schema::some_table_16::field_7, compile_time_test_schema::some_table_16::field_8, compile_time_test_schema::some_table_16::field_9), (compile_time_test_schema::some_table_17::id, compile_time_test_schema::some_table_17::field_0, compile_time_test_schema::some_table_17::field_1, compile_time_test_schema::some_table_17::field_2, compile_time_test_schema::some_table_17::field_3, compile_time_test_schema::some_table_17::field_4, compile_time_test_schema::some_table_17::field_5, compile_time_test_schema::some_table_17::field_6, compile_time_test_schema::some_table_17::field_7, compile_time_test_schema::some_table_17::field_8, compile_time_test_schema::some_table_17::field_9)))))))))))))))) as diesel::SelectableExpression<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_1::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_2::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_3::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_4::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_5::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_6::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_7::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_8::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_9::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_10::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_11::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_12::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_13::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_14::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_15::table, diesel::internal::table_macro::SelectStatement<diesel::internal::table_macro::FromClause<diesel::internal::table_macro::JoinOn<diesel::internal::table_macro::Join<compile_time_test_schema::some_table_16::table, compile_time_test_schema::some_table_17::table, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_16::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_17::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_15::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_16::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_14::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_15::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_13::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_14::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_12::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_13::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_11::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_12::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_10::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_11::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_9::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_10::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_8::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_9::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_7::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_8::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_6::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_7::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_5::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_6::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_4::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_5::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_3::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_4::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_2::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_3::id>>>>>>, diesel::internal::table_macro::Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_1::id>, diesel::internal::table_macro::NullableExpression<compile_time_test_schema::some_table_2::id>>>>>>, polarity:Positive), []) } }"
About notably fourth block:
Looks like the fields of the table (even if unused afterwards) intervene a lot here. Removing them from there by doing something similar to this: https://github.com/Ten0/diesel/commit/b4fcea001f7cfc76098f2174e79521aeff74d79b appears to significantly reduce compilation time, but does not remove the exponential behavior.
NB: that commit is based on an older version of Diesel that would make it easier to try and remove the QuerySource bound from building the join sequence to see if that works around the issue, which is hard in current version because of the lifetime requirement in the query builder (#2931) that makes it necessary to have the bound on the Join
type. (That could probably be fixed by using the first design suggested at https://github.com/diesel-rs/diesel/discussions/2984#discussion-3749047 but I figured it would probably be easier to just test on an old version whether that actually fixes the issue before doing that huge work)
It's interesting that not appending to the large tuple is expensive, but rather than that checking if a select clause is valid. The corresponding trait impl is rather simple: https://github.com/diesel-rs/diesel/blob/5c0452eae52ebd5ec28f489ce1d395c4330936c2/diesel/src/type_impls/tuples.rs#L193
Btw: @Ten0 It would be great to land the postgres row-by-row PR soon, so that I can at least release a 2.0.0-rc.1 version.
I spend a bit more time to look into this. Commenting out the following trait bounds reduces compilation time drastically for me (from 5s to < 1s for 17 joins)
https://github.com/diesel-rs/diesel/blob/17c1bb42894ff2fad44331d27ca46378dd1f3f2f/diesel/src/type_impls/tuples.rs#L194 https://github.com/diesel-rs/diesel/blob/17c1bb42894ff2fad44331d27ca46378dd1f3f2f/diesel/src/type_impls/tuples.rs#L200
Interestingly both impls needs to be removed. Unfortunately are both impls required for checking whether something is selectable for a given table or not.
The following traits are involved there:
pub trait SelectableExpression<QS: ?Sized>: AppearsOnTable<QS> {}
pub trait AppearsOnTable<QS: ?Sized>: Expression {}
pub trait Expression {
type SqlType: TypedExpressionType;
}
pub trait TypedExpressionType {}
They are all implemented for tuples of various sizes. I guess that rustc is doing a lot more work as required there. Something like it starts checking if (some, large, tuple, (nested, tuple)): SelectableExpression<QS>
holds by first checking the bound T: SelectableExpression<QS>
for all tuple members. This implies checking all of the parent traits as well. Some of the tuple members are tuples itself, so this is a quite recursive process. Likely it is checking all of the parent traits again later on because there is Self: AppearsOnTable<QS>
bound there as well. The same thing likely happens for resolving the parent traits as well, as they also depend on another level of parent traits.
I've tried to put that observation in a minimal example, but I haven't been able to reproduce it there yet. Likely I miss an important detail or just choose too small tuple sizes. @lqd are there any easy ways to check that hypothesis through rustc logging/instrumentation?
So I started the work on this again today, findings/recap:
We have 3 separate sub-issues:
- Diesel has the compiler check a ton of trait bounds when building a plain join sequence. In particular,
SelectableExpression
andAppearsOnTable
. - Compiler seems to be extremely slow at checking these bounds.
- On our biggest crate (but no minimal repro as of yet) we re-typecheck the whole crate no matter what we change. That seems to not be the case for my current minimal repro.
I tackled part of 1:
a. https://github.com/Ten0/diesel/tree/f013252e34151431d405d8abd26b6e038e38377e (removing default selection) shows very noticeable improvement (from 2m10s to 20s on our largest crate). This seems to be essentially a sound approach to avoid checking so many SelectableExpression
and AppearsOnTable
bounds. (couldn't think of unsoundness/broken stuff but you're welcome to think about it as well)
That seems to be a reasonable first step (obviously will need some cleaning/feature flagging or table!
setting...)
I think not having a default select expression would be a reasonable default, esp. since we now have Selectable
and we (me & coworkers) have deemed leaving the default clause a bad enough practice that we prohibit it because it:
- Selects unnecessary stuff
- Is error-prone as it relies on default field order, and that field order is declared very far apart from the query (in
schema.rs
) and subject to somewhat-automated change through migrations that would not have the user reconsider all the related queries.
Next steps to further improve on 1 enough to get to a reasonable compile time would be:
b. since even after that most of the time is still spent checking trait bounds on huge nested SelectStatement<Join<SelectStatement...
sequences, trying to simplify the output structs for join-related stuff. Ideally I'd like to not even go through select statement and not check validity of each such inner select statement before building a final one that's not nested so much.
Possibly we would then run into requiring refactoring serialization to allow serializing stuff that is not pre-allocated in the query, allowing to nest less stuff. (as mentionned here).
Pushing further on 1 or 2 or 3 would probably make dev flow reasonable. (we aim for <~2s before we get typecheck feedback in IDE) I estimate 3 to be more likely than 2 to uncover something that would be actionable, and less time-consuming to work on for now than 1.b.
So my next steps will probably be to: A. PR 1.a B. Try and minimize a repro for sub-issue 3, but if 3 turns out to be a dead end then I may come back to 1.b.
@Ten0 Just wanted to thank you on this investigation. I've been subscribed to this issue because I have a production codebase suffering from this typeck issue as well.
Just wanted to thank you on this investigation. I've been subscribed to this issue because I have a production codebase suffering from this typeck issue as well.
Thank you! :) In this kind of scenario you may generally want to upvote the opening message as that gives a simple way to have an idea of how many people are impacted. :)
feature flagging or
table!
setting
@weiznich any strong preference for either of these two?
Sorry to say that, but I would like to avoid both. In my opinion it is a really bad idea to make this behaviour configurable, as it makes it even harder to document what joins will do in diesel. That's already a large issue as it's not obvious for may users. Adding further configurations there will really hurt and have non-local effects.
It might be a better solution to just somehow skip the checks to AppearsOnTable
+ SelectableExpression
for those nested default select clauses at all. We already know that they are valid, because the default select clause of each table is valid.
Sorry to say that, but I would like to avoid both. In my opinion it is a really bad idea to make this behaviour configurable, as it makes it even harder to document what joins will do in diesel. That's already a large issue as it's not obvious for may users. Adding further configurations there will really hurt and have non-local effects.
It might be a better solution to just somehow skip the checks to
AppearsOnTable
+SelectableExpression
for those nested default select clauses at all. We already know that they are valid, because the default select clause of each table is valid.
How about just removing default select clauses altogether then? Looks like this would avoid:
- "makes it even harder to document what joins will do in diesel"
- "have non-local effects"
- "Selects unnecessary stuff"
- "Is error-prone"
That seems particularly acceptable now that we have Selectable
. Overall that would simplify a bunch of things.
Removing the default select clause would be an option and I agree that it might be desirable for the reasons listed. But I feel that's a too large breaking change for now. Basically all existing code (that does use a stable release from crates.io) relies on this. So just removing it now would unfortunately impact to much code in a non-trivial way. If we plan to do this someday we should introduce a proper deprecation period for this feature + offer a complete migration story before finally removing this feature.
I've put together https://github.com/weiznich/diesel/commit/567bb1ddebb882092f7a757f905a6ea043600cfb which skips the SelectableExpression
check for the DefaultSelection
of inner joins. This should not be a breaking change at all and this shows quite significant reductions in compile times for your example above. Please note that this approach would require additional work to figure out which other traits can be skipped as well. Maybe it's even possible to delay checking the Expression
and ValidGrouing<>
bound as well until the query is actually executed. This would allow to always set a custom select clause to avoid this checks too. In my opinion that's the better approach for now.
I've pushed to your speedup_compile_times_for_joins
one extra commit that was required to make stuff like this compile:
let q = schema::some_table_1::table
.inner_join(schema::some_table_2::table)
.inner_join(schema::some_table_3::table.inner_join(schema::some_table_4::table));
With this additional change I was able to compile our main crate, and that took 25s (instead of 20s for the no-default-selection approach). (I suspect the difference is due to the still-present requirement of checking AppearsOnTable
for the default select clauses for each table present in the join - although only once now - which I also wish we could skip.)
However, this approach seems to start allowing invalid queries of this kind:
let q: (
(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32),
(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32),
(
(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32),
(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32),
),
) = schema::some_table_1::table
.inner_join(schema::some_table_4::table)
.inner_join(schema::some_table_3::table.inner_join(schema::some_table_4::table))
.get_result(db)
.unwrap();
(notice how some_table_4
appears twice in this query)
In other words, the following statement seems to be invalid when several join chains come into play: "combining two valid selectable expressions for both tables will always yield a valid selectable expressions for the whole join".
On the current master, this correctly fails to typecheck.
NB: Another advantage of allowing to remove default selections for tables would be that it's not required anymore to increase diesel's compilation time a ton with the n-column-tables features as long as you never select all of those columns at the same time (which is also the case for us).
NB2: No-default-selection seems to suffer from a similar issue where the following also typechecks:
let q: i32 = schema::some_table_1::table
.inner_join(schema::some_table_4::table)
.inner_join(schema::some_table_3::table.inner_join(schema::some_table_4::table))
.select(schema::some_table_1::id)
.get_result(db)
.unwrap();
My guess would be this means that AppearsOnTable
for the on clauses is never checked.
@Ten0 I've pushed another update that addresses the issues you've found. I continue to see an speedup from ~5s down to < 1s for your example repository with an example join with 17 tables for cases where the incremental compilation does not cache the results. Rustc self compile does report that the longest typecheck query now takes less than 20ms (400ms overall for typecheck). I feel that are good results without doing major breaking changes. (As outlined above I feel that's not possible that close to a release anymore).
The next step for future speedups on your code base would likely to check the self compile output again to see where the time is spend now. It's quite possible that there are other places with could need some optimization as well.
The current state of #3288 looks good to me (almost) for merge, and the state of the investigation on this issue is such that I'm fine with 2.0 release at this point :) (looks like further improvements are unlikely to be easy breaking changes)
On the topic of this issue still, I get 28s of compilation with this (vs 20 and 25 with previous iterations - that weren't completely sound). The self-profiling output of my crate seems to show that the vast majority of the time is still spent checking Diesel trait bounds - so I don't think we can resolve this issue just yet (although it will probably require a rename ^^).
On other news, I've found #2931 to be responsible for some part of the compilation time there, as it introduces this kind of bounds checks: https://github.com/diesel-rs/diesel/pull/2931/files#diff-7ca93b1537271394be3fa89ae39f924f906c98c2f01520247ee2a38a38fcb029R228-R231 a bit everywhere
All because of: https://github.com/diesel-rs/diesel/pull/2931/files#diff-4c3c5e08e6c23444455157fb9a8be55d84d7df7198e8c69114d664bb354d2e61R48-R51
- itself because https://github.com/diesel-rs/diesel/pull/2931/files#diff-7ca93b1537271394be3fa89ae39f924f906c98c2f01520247ee2a38a38fcb029L162 is not possible anymore because of the lifetime stuff.
On the issue reproduction crate I get:
- 14 Joins: before: 2.3s, after: 3.2s
- 17 Joins: before: 3.9s after: 6.42s
(#3288 performs much better than both)
-> Attempting to decouple QueryFragment
implementations from the query builder representations using this design (re-allowing https://github.com/diesel-rs/diesel/pull/2931/files#diff-7ca93b1537271394be3fa89ae39f924f906c98c2f01520247ee2a38a38fcb029L162) would consequently be likely to show significant compilation time improvement (while also overall simplifying the query builder representations) - although we have to keep in mind the following comment.
That however is a large enough work (if it even works) that I'm fine with not delaying 2.0 further, esp. since I still want to investigate 3 before. :)
On other news, I've found #2931 to be responsible for some part of the compilation time there, as it introduces this kind of bounds checks: https://github.com/diesel-rs/diesel/pull/2931/files#diff-7ca93b1537271394be3fa89ae39f924f906c98c2f01520247ee2a38a38fcb029R228-R231 a bit everywhere
All because of: https://github.com/diesel-rs/diesel/pull/2931/files#diff-4c3c5e08e6c23444455157fb9a8be55d84d7df7198e8c69114d664bb354d2e61R48-R51
- itself because https://github.com/diesel-rs/diesel/pull/2931/files#diff-7ca93b1537271394be3fa89ae39f924f906c98c2f01520247ee2a38a38fcb029L162 is not possible anymore because of the lifetime stuff.
Thanks for doing this investigation. Those links are broken for me, or at least they do not jump to any line. Maybe you can replace them with links to the corresponding trait bounds on the master branch?
Those links are broken for me, or at least they do not jump to any line
behavior for me on Firefox and Chromium is that they end up jumping to the correct place if you wait long enough (~15s ^^)
@Ten0 Same for me, 15s! haha
Seems like I did not wait long enough. It's working now :+1:
81 tables with 117 joins are very slow too.
@dancixx As long as you don't provide any new information these kind of posts is highly discouraged as they are not helpful at all. At least you would need to provide an reproducible example here, otherwise please stop posting to old issues.