Slow typechecking/borrow checking

I made a crate that involves generating Rust types from some C code with a proc macro. This works surprisingly well, except for one thing: compile times.

There are a few hundred of the generated types (500-ish) and the crate takes ~8 seconds to build on my machine (Ryzen 7900). The bottleneck isn't codegen, but rather type checking and borrow checking:

time:   2.159; rss:  372MB ->  575MB ( +202MB)	type_check_crate
time:   1.800; rss:  575MB ->  817MB ( +242MB)	MIR_borrow_checking

This is from the code at A few build perf improvements by gnosek · Pull Request #43 · falcosecurity/plugin-sdk-rs · GitHub where I managed to cut down the build time by ~800ms by reducing the use of generics, but it's still slower than I'd hope. Not enabling the new full-schema feature makes the crate compile in ~2 seconds (as there are only 2 event types to handle, not hundreds) but I'd like to always support the full event schema if possible with reasonable build times.

With -Znext-solver, the type checking time explodes:

time:  32.740; rss:  374MB ->  612MB ( +239MB)	type_check_crate

(before this PR it was >1 minute I think).

With -Znext-solver=coherence, it's roughly the same as on stable:

time:   2.091; rss:  376MB ->  576MB ( +200MB)	type_check_crate

The generated code looks like this (except with the full-schema feature, there are ~500 types, not 2, but that's not really human-readable):

I don't see anything particularly egregious in the generated code (except at the end, where it looks like the formatter gave up), so am I missing some low hanging fruit or should I just accept the compile times?

While I was writing this post, I tried making this: plugin-sdk-rs/falco_event_derive/src/event_info.rs at main · falcosecurity/plugin-sdk-rs · GitHub into a free function (so we don't cast Self to a trait). It looked like it helped a lot but then I couldn't reliably reproduce the difference, so maybe it was a fluke after all.

I don't know if this will help, but I would try making the generated read() and write() functions (and thus their traits) non-generic, using &mut dyn Iterator and &mut dyn Write.

Thanks for the suggestion, though unfortunately it didn't do much :slight_smile:

time:   2.217; rss:  375MB ->  580MB ( +205MB)	type_check_crate
time:   1.773; rss:  580MB ->  817MB ( +238MB)	MIR_borrow_checking

Is there a way to dig deeper into the timings? I tried the self-profile flamegraphs but they just reported a flat "typechecking" bar without any further details.

I guess I can run the compiler under perf but I doubt I'll be able to interpret the results, so I'm hoping for some middle ground.