Using Diesel's joins has projects type check in time exponential in the number of joins, despite incremental compilation.
This leads to crates using Diesel quickly getting up to unreasonable IDE feedback time. (cargo check
after a simple unrelated change takes 2min to start giving compilation feedback in one of our crates managing a complex schema of ~100 tables due to this, with some small function bodies taking up to ~5s to typecheck!)
We'll generally be using this repo and https://blog.rust-lang.org/inside-rust/2020/02/25/intro-rustc-self-profile.html
cargo install --git https://github.com/rust-lang/measureme crox
rustup install nightly
git clone https://github.com/Ten0/diesel_3223_repro.git
cd diesel_3223_repro/compile_time_test
-
Compile a first time to setup incremental compilation cache for the crate
cargo +nightly rustc --lib --profile check
-
Go edit
src/bodies.rs
:- Uncomment the
different_each_regen
function - Add one
println!("Helloo!");
- Uncomment the
-
Compile a second time with self-profiling enabled, then turn generated file into something Chrome can open
cargo +nightly rustc --lib --profile check -- -Zself-profile -Zself-profile-events=default,args crox --minimum-duration 2 compile_time_test-<number_of_file_just_created>.mm_profdata
-
Follow the self-profiling guide to open the file in Chrome, that is:
- Open Chrome
- Open the Developer Tools console by pressing Ctrl + Shift + i (Windows/Linux) or Cmd + Option + i (macOS)
- Click the Performance tab at the top of the console.
- Click the "Load profile" button which looks like an arrow pointing up.
- Select the chrome_profiler.json file we created.
-
Go add one join to
src/bodies.rs
- Uncomment one of the two joins in
body_0
:schema::some_table_5::table.inner_join( schema::some_table_6::table/*.inner_join(schema::some_table_7::table)*/, ),
- Comment the
different_each_regen
function - Do steps 1 to 4 again (preparing incremental compilation cache, changing one function elsewhere in the code such that we won't hit any previous incremental compilation cache, check with profiling enabled, open results)
- Uncomment one of the two joins in
-
typeck
times:nb_joins time (ms) 4 204 5 296 6 410 7 561 10 1290 11 1660 14 3240 17 5880 20 9710 21 11560 25 20810 It appears the
typeck
time formula fits very well with an exponential curve:
$t = a \times b^n$ + c
where$n$ is the number of joins,$a$ = 552.792,$b$ = 1.15846,$c$ = -894: (You may look for other fitting curves at https://www.dcode.fr/function-equation-finder - notably it's not completely impossible to find ~matching curves with polynomial of degree ~3)
You may also notice that check_mod_privacy
also starts taking an unreasonable amount of time (even more non-linear) above 14 joins but 14 joins rarely happens in practice and as long as I get IDE feedback on the rest, which runs before, I'm fine so that hasn't been an issue for us yet. Nevertheless I'm pointing it out in case someone is interested in investigating this...