Why cargo timings shows that single version of image crate was compiled multiple times?

Hi,

To verify absurdly long compilation times(>80 minutes), I tried to check what happens with --timings flag.

The problem happens only with release flag, so probably this is caused by llvm optimizations, but I started to check time baseline with debug build and I found on graph two long image-rs elements - this would be expected if I would compile two different image crate versions, but in Cargo.lock I see only one occurrence of image crate.

Why rust compiles twice the same version of library? Is this maybe a preparation stage and real compilation or maybe a bug?

Cargo lock - czkawka/Cargo.lock at master · qarmin/czkawka · GitHub
Debug timings - https://github.com/slint-ui/slint/files/14344529/debug_cargo-timing-20240220T105545Z.html.zip
Release timings - https://github.com/slint-ui/slint/files/14344530/release_cargo-timing-20240220T110513Z.html.zip (what is a little strange is that image-rs library compiles faster with release mode than with debug)

It looks like the image crate is used both at runtime by your own code and at compile time by i-slint-compiler. As you aren't cross-compiling it would technically be possible to reuse the same image crate, but it doesn't get reused because build dependencies are unconditionally built with optimizations disabled to reduce the time it takes to compile when a dependency is only used at build time, like is the case most of the time. It unfortunately has the side effect of causing compilation to get longer when a dependency is used both at build time and at runtime.

3 Likes

For reference on my system compiling image v0.24.8 + all it's dependencies in release mode on a single efficiency core took a total of 75s. I used a single core to simulate the effect of other crates keeping the rest of the cores busy and used an efficiency core because it has a lower turbo frequency (which wouldn't be reached anyway when compiling other crates at the same time)

Maybe in the debug build compilation was restricted to a single core due to other crates getting compiled, while in the release build it happened to be able to fill some gaps allowing it to use multiple cores for compilation for at least part of the time?

Are you using fat LTO? It seems like it is only using a single core during most of the time compiling krokiet. Fat LTO can only use a single core. Using thin LTO would allow using all cores, which should be several times as fast.

I compiled app with default cargo commands cargo build and cargo build --release, so lto was not used(at least it was not enabled by me)

I compiled app with RUSTFLAGS="-Zself-profile" cargo +nightly rustc --release and I see that most of the time took not LLVM, but rust

+-------------------------------------------------------------------------+-----------+-----------------+----------+------------+
| Item                                                                    | Self time | % of total time | Time     | Item count |
+-------------------------------------------------------------------------+-----------+-----------------+----------+------------+
| mir_pass_scalar_replacement_of_aggregates                               | 4933.25s  | 96.338          | 4933.25s | 4860       |
+-------------------------------------------------------------------------+-----------+-----------------+----------+------------+
| LLVM_module_optimize                                                    | 35.17s    | 0.687           | 35.17s   | 17         |
+-------------------------------------------------------------------------+-----------+-----------------+----------+------------+
| LLVM_passes                                                             | 34.53s    | 0.674           | 34.58s   | 1          |
+-------------------------------------------------------------------------+-----------+-----------------+----------+------------+
| LLVM_lto_optimize                                                       | 34.15s    | 0.667           | 34.15s   | 16         |
+-------------------------------------------------------------------------+-----------+-----------------+----------+------------+
| finish_ongoing_codegen                                                  | 30.40s    | 0.594           | 30.40s   | 1          |
+-------------------------------------------------------------------------+-----------+-----------------+----------+------------+
| LLVM_module_codegen_emit_obj                                            | 28.04s    | 0.548           | 28.04s   | 17         |
+-------------------------------------------------------------------------+-----------+-----------------+----------+------------+
| typeck                                                                  | 3.45s     | 0.067           | 3.60s    | 5318       |
+-------------------------------------------------------------------------+-----------+-----------------+----------+------------+
| codegen_crate                                                           | 2.25s     | 0.044           | 4942.10s | 1          |
+-------------------------------------------------------------------------+-----------+-----------------+----------+------------+
| LLVM_thin_lto_import                                                    | 2.05s     | 0.040           | 2.05s    | 16         |
+-------------------------------------------------------------------------+-----------+-----------------+----------+------------+
| run_linker                                                              | 1.98s     | 0.039           | 1.98s    | 1          |
+-------------------------------------------------------------------------+-----------+-----------------+----------+------------+

should I open issue in rust repo?

Yes, please open an issue. mir_pass_scalar_replacement_of_aggregates is not supposed to take that long at all.

1 Like