Skip to content

Incremental compilation on Windows is slow because of hard links #137560

Open
@kryptan

Description

@kryptan

Every time I recompile my Rust project after a change it takes 2 or 3 seconds. I was wondering where that time is spent. I used the measureme/summarize tool to profile the rust compiler and it showed me that most time is spent in the codegen_copy_artifacts_from_incr_cache stage:

+--------------------------------------------------------+-----------+-----------------+----------+------------+-----------------------+---------------------------------+
| Item                                                   | Self time | % of total time | Time     | Item count | Incremental load time | Incremental result hashing time |
+--------------------------------------------------------+-----------+-----------------+----------+------------+-----------------------+---------------------------------+
| codegen_copy_artifacts_from_incr_cache                 | 12.24s    | 83.333          | 12.24s   | 255        | 0.00ns                | 0.00ns                          |
+--------------------------------------------------------+-----------+-----------------+----------+------------+-----------------------+---------------------------------+
| run_linker                                             | 448.51ms  | 3.054           | 448.51ms | 1          | 0.00ns                | 0.00ns                          |
+--------------------------------------------------------+-----------+-----------------+----------+------------+-----------------------+---------------------------------+
| incr_comp_prepare_session_directory                    | 416.99ms  | 2.840           | 416.99ms | 1          | 0.00ns                | 0.00ns                          |
+--------------------------------------------------------+-----------+-----------------+----------+------------+-----------------------+---------------------------------+
| LLVM_passes                                            | 414.15ms  | 2.820           | 414.15ms | 1          | 0.00ns                | 0.00ns                          |
+--------------------------------------------------------+-----------+-----------------+----------+------------+-----------------------+---------------------------------+
| copy_all_cgu_workproducts_to_incr_comp_cache_dir       | 349.22ms  | 2.378           | 349.22ms | 1          | 0.00ns                | 0.00ns                          |
+--------------------------------------------------------+-----------+-----------------+----------+------------+-----------------------+---------------------------------+
| codegen_crate                                          | 264.25ms  | 1.800           | 375.35ms | 1          | 0.00ns                | 0.00ns                          |
+--------------------------------------------------------+-----------+-----------------+----------+------------+-----------------------+---------------------------------+
...   

The reported time is larger than the actual time, probably because of multithreading.

This stage involves creating hard links.

Process Monitor shows that there are many SetLinkInformationFile syscalls some of which take 100-200ms each:

Image

I have observed this behaviour on many different projects.

Steps to reproduce in any Rust project of non-trivial size are:

  1. cargo build
  2. Make any small change, like changing a string literal.
  3. cargo rustc -- -Z self-profile
  4. summarize summarize <filename>.mm_profdata

Looks like creating hard links is sometimes very slow on Windows. Maybe some other strategy can be used to avoid creating so many hard links?


rustc 1.87.0-nightly (f8a913b13 2025-02-23)
binary: rustc
commit-hash: f8a913b1381e90379c7ca63ac2b88b9518936628
commit-date: 2025-02-23
host: x86_64-pc-windows-msvc
release: 1.87.0-nightly
LLVM version: 20.1.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-incr-compArea: Incremental compilationI-compiletimeIssue: Problems and improvements with respect to compile times.O-windowsOperating system: WindowsT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions