Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vec-growing logic emitted for Vecs which never grow #118563

Open
LingMan opened this issue Dec 3, 2023 · 3 comments
Open

Vec-growing logic emitted for Vecs which never grow #118563

LingMan opened this issue Dec 3, 2023 · 3 comments
Labels
I-heavy Issue: Problems and improvements with respect to binary size of generated code. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Comments

@LingMan
Copy link
Contributor

LingMan commented Dec 3, 2023

Consider these two examples:

pub fn foo(sizes: &[u64]) -> u64 {
    let mut top = Vec::with_capacity(1);
    for &size in sizes {
        /*if top.capacity() <= top.len() {
            unsafe { std::hint::unreachable_unchecked() }
        }*/
        top.push(size);
        top.pop();
    }
    top.iter().sum()
}
pub fn bar(sizes: &[u64]) -> u64 {
    const TOP_ELEMENTS: usize = 3;
    let mut top = Vec::with_capacity(TOP_ELEMENTS + 1);
    for &size in sizes {
        /*if top.capacity() <= top.len() {
            unsafe { std::hint::unreachable_unchecked() }
        }*/
        let i = 0; //top.partition_point(|&cur| cur > size);
        top.insert(i, size);
        top.truncate(TOP_ELEMENTS);
    }
    top.iter().sum()
}

Godbolt: https://rust.godbolt.org/z/PhrMr7dYr

Neither are ever going to grow their Vec from the initial size. Yet, RawVec::reserve_for_push and friends are emitted when compiling.
Uncommenting the unreachable_unchecked hints allows the optimizer to clean everything up. Might be asking a lot of the compiler but it would be great if it could figure that out by itself.

Tested with Rust 1.74 and with 1.76.0-nightly (87e1447 2023-11-30).

@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Dec 3, 2023
@the8472
Copy link
Member

the8472 commented Dec 3, 2023

On nightly you can use push_within_capacity to avoid the resizing machinery.

@LingMan
Copy link
Contributor Author

LingMan commented Dec 3, 2023

Not really, I need the insert semantic. The version with push is just an example I came up with while poking at it. And I'm on stable.

Will probably use the arrayvec crate for now.

@jhorstmann
Copy link
Contributor

Looks similar to #114334, but that had pop followed by push.

#105156 and #82801 are also related to better capacity tracking.

@Noratrieb Noratrieb added T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. I-heavy Issue: Problems and improvements with respect to binary size of generated code. T-libs Relevant to the library team, which will review and decide on the PR/issue. and removed needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels Dec 15, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
I-heavy Issue: Problems and improvements with respect to binary size of generated code. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

5 participants