Performance regression between v1.76.0 and v1.77.2
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
Code
I'm working on some low-level bit-manipulation code, and discovered that v1.77 generates code that runs at about half the speed compared to the output of v1.76. Since the v1.77 release notes don't mention anything about an LLVM upgrade I figure there must be something going wrong in the rustc LLVM IR generation.
Compilable reproduction:
The inner loop is decode_u32(), which is sort of ugly but isn't doing anything especially complex.
pub fn decode_u32(buf: &[u8; 5]) -> (u32, usize) {
if buf[0] < 0x80 {
return (buf[0] as u32, 1);
}
if buf[0] < 0xF0 {
let x = u32::from_le(unsafe {
ptr::from_ref(buf).cast::<u32>().read_unaligned()
});
if buf[0] < 0b11000000 {
let decoded = (x & 0x3F) | ((x & 0xFF00) >> 2);
return (decoded, 2);
}
if buf[0] < 0b11100000 {
let decoded = (x & 0x1F) | ((x & 0xFFFF00) >> 3);
return (decoded, 3);
}
let decoded = (x & 0x0F) | ((x & 0xFFFFFF00) >> 4);
return (decoded, 4);
}
let decoded = u32::from_le(unsafe {
ptr::from_ref(buf)
.cast::<u8>()
.add(1)
.cast::<u32>()
.read_unaligned()
});
(decoded, ((buf[0] & 0x0F) + 2) as usize)
}
The exact timing varies depending on the distribution of input values. The attached reproduction uses a distribution for which the new code is about twice as slow.
$ RUSTFLAGS="-Copt-level=3" cargo +1.76.0 build --release
$ time ./target/release/main
real 0m4.182s
user 0m4.181s
sys 0m0.000s
$ RUSTFLAGS="-Copt-level=3" cargo +1.77.2 build --release
$ time ./target/release/main
real 0m7.699s
user 0m7.694s
sys 0m0.004s
Version it worked on
It most recently worked on: Rust v1.76.0
Version with regression
rustc --version --verbose:
$ rustc +1.77.2 --version --verbose
rustc 1.77.2 (25ef9e3d8 2024-04-09)
binary: rustc
commit-hash: 25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04
commit-date: 2024-04-09
host: x86_64-unknown-linux-gnu
release: 1.77.2
LLVM version: 17.0.6
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the attached Cargo.toml and main.rs, reproduce the timings using the rustc 1.76.0 and 1.77.2 commands, and inspect the decode_u32() inner loop and generated LLVM-related output. Trace the regression to the rustc LLVM IR generation change and verify that the reproduction no longer shows the reported slowdown.
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
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100