Skip to content

Add if len > CAP { unreachable_unchecked() }#314

Open
barakugav wants to merge 2 commits into
bluss:masterfrom
barakugav:assume-len
Open

Add if len > CAP { unreachable_unchecked() }#314
barakugav wants to merge 2 commits into
bluss:masterfrom
barakugav:assume-len

Conversation

@barakugav

@barakugav barakugav commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

First of all, love the library! use it all the time 😄

This PR add a if len > CAP { unreachable_unchecked() } call in ArrayVec::len().
We know this assumption, and telling the compiler about it let it generate better code and eliminate some bound checks.

It also include a small benchmark for ArrayVec::clone() that demonstrate the (massive) speed up.

# before
> cargo bench clone
running 2 tests
test clone_512 ... bench:         345 ns/iter (+/- 20) = 1484 MB/s
test clone_8   ... bench:           4 ns/iter (+/- 0) = 2000 MB/s

# after
> cargo bench clone
running 2 tests
test clone_512 ... bench:         205 ns/iter (+/- 15) = 2497 MB/s
test clone_8   ... bench:           2 ns/iter (+/- 0) = 4000 MB/s

Clone is my specific use case, but im sure other generated code is more optimized when the compiler knows this.

Thanks for the support in advance ❤️

Comment thread build.rs Outdated
Comment on lines +14 to +29
fn rustc_version() -> Option<u32> {
// Code copied from cxx crate

let rustc = std::env::var_os("RUSTC")?;
let output = std::process::Command::new(rustc)
.arg("--version")
.output()
.ok()?;
let version = String::from_utf8(output.stdout).ok()?;
let mut pieces = version.split('.');
if pieces.next() != Some("rustc 1") {
return None;
}
let minor = pieces.next()?.parse().ok()?;
Some(minor)
}

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two big questions for the maintainer here: should we add a build script? Going from no build script to having one is a step back.

Second, reviewing the function: this function rustc_version must be removed. Use a maintained crate to do this - preferably autocfg - don't copy/code your own version check. The reason is long-term maintainability.

Suggested resolution: Wait until the MSRV allows this without trouble. Publish a new 0.8.x soon with updated MSRV (and a slowly sliding MSRV policy), use this without build.rs.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i found a workaround that doesn't require build.rs, tell me what you think

@barakugav

Copy link
Copy Markdown
Contributor Author

@bluss I replaced hint::assert_unchecked(len <= CAP) with if len > CAP { hint::unreachable_unchecked() }, which is stable in 1.51, and got the same speedup/asm. build.rs removed.

@barakugav barakugav changed the title Add hint::assert_unchecked(len <= CAP) Add if len > CAP { unreachable_unchecked() } Jul 9, 2026
@barakugav

barakugav commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

oh, unreachable_unchecked is stable since 1.27 but as const fn only from 1.57... at least is lower than assert_unchecked'a 1.81 requirement.
This can wait until we bump msrv to 1.57, or i can revert to the build.rs solution. Either way, i think this optimization can have a large impact for all users, so please consider it 🙏

@bluss

bluss commented Jul 9, 2026

Copy link
Copy Markdown
Owner

We're fixing clone in the other PR, so we need one more example for when this helps in this case. I thought "codegen tests" are a good way to look at this, so if it's possible to make one like for clone it would be good.

Alt solution, add .len_dynamic() which is non-const and use it in critical places in the crate. It would be internal, so not in the API, so only help internal methods.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants