Expand description
§Branches
branches
provides branch prediction hints, control flow assumptions, abort, and manual data prefetch (read & write) helpers for performance optimization, using stable Rust primitives where available and falling back to core::intrinsics
on nightly.
§Usage
To use branches
, add the following to your Cargo.toml
file:
[dependencies]
branches = "0.2"
For a no_std environment, disable the default features by adding the following to your Cargo.toml
instead:
[dependencies]
branches = { version = "0.2", default-features = false }
§Functions
The following functions are provided by branches
:
likely(b: bool) -> bool
: Returns the input value but provides hints for the compiler that the statement is likely to be true.unlikely(b: bool) -> bool
: Returns the input value but provides hints for the compiler that the statement is unlikely to be true.assume(b: bool)
: Assumes that the input condition is always true and causes undefined behavior if it is not. On stable Rust, this function usescore::hint::unreachable_unchecked()
to achieve the same effect.abort()
: Aborts the execution of the process immediately and without any cleanup.prefetch_read_data<T, const LOCALITY: i32>(addr: *const T)
: Hints the CPU to load data ataddr
into cache for an upcoming read.LOCALITY
selects cache behavior (e.g. 0 = L1, 1 = L2, 2 = L3, other = non‑temporal or arch default). Unsafe:addr
must be a valid, properly aligned pointer; may not alias freed or unmapped memory.prefetch_write_data<T, const LOCALITY: i32>(addr: *const T)
: Hints the CPU to load a line for an upcoming write. SameLOCALITY
semantics as above. Unsafe for the same reasons, and you must ensure future writes are plausible (avoid prefetching arbitrary / constant addresses).
Guidelines:
- Only prefetch a small distance ahead (tune empirically).
- Too-far or excessive prefetching can evict useful cache lines.
- Never rely on prefetch for correctness; it is purely a performance hint.
Here’s an example of how you can use likely
to optimize a function:
use branches::likely;
pub fn factorial(n: usize) -> usize {
if likely(n > 1) {
n * factorial(n - 1)
} else {
1
}
}
Loop manual prefetch example:
use branches::{prefetch_read_data, prefetch_write_data};
pub fn accumulate(a: &[u64], out: &mut [u64]) -> u64 {
let mut sum = 0u64;
let len = a.len().min(out.len());
for i in 0..len {
// Prefetch the next iteration's data (read) into L1
if i + 16 < len {
unsafe { prefetch_read_data::<u64, 0>(a.as_ptr().wrapping_add(i + 16)); }
unsafe { prefetch_write_data::<u64, 0>(out.as_ptr().wrapping_add(i + 16)); }
}
sum += a[i];
out[i] = sum;
}
sum
}
By correctly using the functions provided by branches, you can achieve a 10-20% improvement in the performance of your algorithms.
§License
branches
is licensed under the MIT license. See the LICENSE
file for more information.
Functions§
- abort
- Aborts the execution of the process immediately and without any cleanup.
- assume⚠
- Informs the optimizer that a condition is always true.
- likely
- Hints to the compiler that the branch condition is likely to be true. Returns the value passed to it.
- prefetch_
read_ data - Prefetches data for reading into the cache.
- prefetch_
write_ data - Prefetches data for writing into the cache.
- unlikely
- Hints to the compiler that the branch condition is unlikely to be true. Returns the value passed to it.