---
# System prepended metadata

title: Parallel Rustc Normalization

---

# Parallel Rustc Normalization

## Summary

Make the current parallel compiler truly available to Rust users, and improve the functions and supporting facilities of the parallel compiler.

## Motivation

Parallelization is an important way to improve the efficiency of the compiler. The parallel rustc working group in the compiler team is responsible for the parallelization of the compiler. At current the working group has been stagnant for a long time due to the exit of the main developer.

Yet the parallel compiler still has considerable value and potential. In [the previous build test](https://github.com/rust-lang/rust/pull/75651#issuecomment-683332949), quite a few parts of the test set achieved huge improvements in wall-time. And many parts of the compilation process, e.g. expansion, have the potential to be parallelized.

## Design

### Make the nightly compiler able to parallelize

Currently users can only use the parallel compiler by installing rust locally from source code with setting `parallel-compiler = true` in `config.toml`. Ideally, the user can choose whether to compile in parallel by setting `-Zthread=n`. The biggest problem here is efficiency of **parallel-queries** system. Enable [parallel-queries](https://github.com/rust-lang/rust/issues/48685) will result in about **5%** [regressive](https://github.com/rust-lang/rust/pull/101566#issuecomment-1276331871) compared to non-parallel mode when setting `-Zthread=1`.

Closing this performance gap as much as possible and enabling parallel-queries by default is the working group's main job. We can optimize the compilation process according to the following strategies to reduce performance regression:

1. Prioritize the refactoring of the code implementation to reduce the number of calls to Lock::lock(). e.g. [commit](https://github.com/rust-lang/rust/pull/101566/commits/105e83cf4d73aaca132438b6628a0f5cfeb8c340), [#101313](https://github.com/rust-lang/rust/pull/101313), [#99702](https://github.com/rust-lang/rust/pull/99702)
2. If 1 does not work well, use GAT to make the two modes(parallel and non-parallel) use different implementations for `Lock`. This relatively increases the size of the rustc binary, and needs some extra efforts to ensure threads safety. Fortunately, we only need to make such changes to a small part of the code. From the results of the [experimental PR](https://github.com/rust-lang/rust/pull/101566), doing so when the query system creates new dep-nodes and accesses the query cache solves nearly half of the regression.

On the other hand, considering the regressive may not be completely eliminated (at least without doing a large-scale refactoring of the compiler code or making it too complex), we need to decide the regressive bound in single-threaded mode. We can discuss this with the rustc-perf working group.

### Measure rustc's performance in a multi-threaded environment

Improve rustc-perf's support for parallel compilers. The total instruction count is difficult to reflect the real compilation efficiency in a multi-threaded environment. We should implement a different counting strategy, such as having only one of the running threads increases the counter.

Special benchmarks for multi-threaded environments need to be added, too. Such as the number of locks and blocking time.

This part of the work is also very important, which makes us able to measure the benefits of parallel compilers to determine the acceptable refressive bound in single-threaded mode.

### Test for parallel compiler

Most of the UI tests in the parallel environment have been fixed, see [here](https://github.com/rust-lang/rust/issues/75760). But these UI tests are only for `-Zthreads=1`, and not for using more threads. And based on some previous experience, `-Zthread=n` does cause ICE issues in real builds. We need to collect and fix these problems.

On the other hand, multithreading can also result in diagnostics not being output in a deterministic order. We may need to do some implementation to solve it, such as changing from "outputting the diagnostics immediately when the compilation fails" to "collecting all the diagnostics first, sorting and then outputting". The order of diagnostics also needs to be determined, such as getting the index of the current rayon iterator task and writing it to each diagnostic.

### Deepen compiler parallelism

Currently the only stage of the compiler that is already parallel is codegen. The part that is being improved is parallel-queries. In addition to this, there are other parts of the compiler that also have the potential to be parallelized.

**Lex parsing, macro expansion, and name resolving** have considerable potential for parallelization. These partial functions are relatively independent to other parts and do not rely on the query system.

### Alternatives

Keep the current implementation based on `#[cfg(parallel_compiler)]` conditional compilation, and let other community components provide parallelized compilers. For example, allowing users to switch to a parallelized compiler version through the rustup tool.

Considering that the efficiency of parallel query is the current bottleneck, this approach can allow general users to fetch the parallel compiler more quickly.

### Working group members

@cjgillot, @bjorn3, @nnethercote, @Kobzol and @SparrowLii would like to be part of the rebooted working group.

Welcome to join if you are also interested in this work!

# Mentors or Reviewers

@cjgillot @bjorn3 @Kobzol are willing to do the review work. Very grateful for their help!

