Skip to content

Parallel dependency source updates #15934

@susitsm

Description

@susitsm

Problem

Currently, source updates are done in a blocking way during dependency resolution. With many different sources (many packages with git path in my case), this can become the bottleneck of cargo update.

Proposed Solution

While querying dependencies, ensure_loaded is called to make sure the dependency source is loaded. Changing it to return a Poll allows processing other dependencies, and their sources, while the source is being downloaded.

Progress bars

Since git sources use progress bars, it must be ensured that running these updates on multiple threads does not create a flickering progress bar (you can observe this in my example during the uncached benchmark, if ran without --quiet). Since the discussion on what and how cargo should display is still ongoing in #8889, I would implement a simple system with the goal of keeping close to the current output: It would show the last started progress bar until finished, then fall back to the previous. This also has the benefit of requiring no new terminal features.

Notes

This issue was moved from the internals forum. Addressing @epage's concerns:

If/when you bring this to the cargo team, it would be good to include reproduction steps as well as characterize the performance impact (when it happens, how slow it can be, and end-user impact).

These benchmarks were created using my example crate with 13 git sources

Starting "cargo update" benchmarks
Uncached, serial, cargo 1.91.0-nightly (840b83a10 2025-07-30):

real	0m18.497s
user	0m6.969s
sys	0m0.435s

Uncached, parallel:

real	0m6.372s
user	0m7.343s
sys	0m0.825s

Cached, serial, cargo 1.91.0-nightly (840b83a10 2025-07-30):

real	0m4.445s
user	0m0.707s
sys	0m0.101s

Cached, parallel:

real	0m1.036s
user	0m1.103s
sys	0m0.246s

With -Zgit=shallow-deps

Uncached, shallow, serial, cargo 1.91.0-nightly (840b83a10 2025-07-30):

real	0m9.295s
user	0m1.116s
sys	0m0.215s

Uncached, shallow, parallel:

real	0m1.521s
user	0m1.479s
sys	0m0.317s

The parallel updates are 2-6x faster than the serial ones. For the cached case, the git updates should be even faster, the bottleneck is updating crates.io dependencies.

In addition to the problems you gave, note that the function you linked to specifically calls out that it is blocking and why.

ensure_loaded is a private function, called in 3 other functions (query, patch and add_sources). Changing ensure_loaded to return a Poll (maybe even renaming it to pend_until_loaded) integrates nicely with query and patch, as they already handle Poll-s. add_sources will need a loop to wait for all pending sources. These changes will bring the performance boost of parallel source updates to all code using these 3 public functions, without a need for any changes.

We've been cautious about what terminal features we take advantage of for maximum compatibility. We've branched out more recently with unicode and hyperlink support. Like those, any progress improvements over what we have today will likely need some kind of end-user control and ideally auto-detection.

The current proposal uses no new terminal features and minimizes the changes to cargo's output

Not quite sure if GlobalContext needs to be thread safe for this. If something can fit within our pre-async async framework, then Sync shouldn't be needed, which describes most of our networking and Source logic.

Right, it is enough to convert the display part to Sync. Even though I think it would be benefical, as it would simplify parallelizing other things without noticable performance impact on serial code, that should be its own discussion.

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-feature-requestCategory: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted`PerformanceGotta go fast!S-needs-team-inputStatus: Needs input from team on whether/how to proceed.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions