rust-lang / rust-lang/rust

`Vec::from_iter` specialization is slower on `TrustedLen` iterators from `thin-vec`

Open
#160,048 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-iterators A-specialization I-slow needs-triage
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

In https://github.com/rust-lang/rust/pull/159974, https://github.com/rust-lang/rust/pull/159975, we found out that updating and enabling "unstable" feature flag in thin-vec makes some new-solver benchmarks slower.

I tried to measure this in isolation on the old version in https://github.com/rust-lang/rust/pull/160010, where the old "unstable" flag only adds TrustedLen impl to thin_vec::IntoIter and thin_vec::Drain. The results for only adding the flag are here and they reproduce the regression: https://github.com/rust-lang/rust/pull/160010#issuecomment-5093128897

Based on the cachegrind diffs, the culprit is mostly in this iterator chain:

https://github.com/rust-lang/rust/blob/d3ea0356830dc019038110eba0bc8f790aaef2e4/compiler/rustc_trait_selection/src/solve/fulfill.rs#L185-L198

pending.drain() creates thin_vec::Drain iterator. The rest of it are iterators from std.

Adding no-op skip(0) before the collect() call disables the specialization (because Skip doesn't implement TrustedLen) and fixes most of the regression: https://github.com/rust-lang/rust/pull/160010#issuecomment-5098416135, but not all of it, so it looks like the problem is not specific to this chain.

If I understand the specialization resolution correctly, the problematic from_iter impl is this one:

https://github.com/rust-lang/rust/blob/d3ea0356830dc019038110eba0bc8f790aaef2e4/library/alloc/src/vec/spec_from_iter_nested.rs#L50-L62

Note that https://github.com/rust-lang/rust/pull/160005 optimizes some of the next-solver data structures, so it's possible the issue will no longer reproduce on this code on main as visibly, but the issue might still exist.

I currently don't have time to research this further and create smaller reproducer, but maybe somebody who has more experience with these specializations has a better idea for what's going on.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the iterator chain in compiler/rustc_trait_selection/src/solve/fulfill.rs and the Vec specialization in library/alloc/src/vec/spec_from_iter_nested.rs. Reproduce the regression with the thin-vec unstable feature and inspect the cachegrind comparisons from PR #160010. Done means identifying the TrustedLen specialization cause and confirming the relevant benchmark no longer regresses.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers, performance
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.