These busy loops burn CPU cycles without doing anything. It is almost always a
better idea to panic!
than to have a busy loop.
Certain regexes that are used with Regex::new
or RegexBuilder::new
may be
replaced by common str
methods, such as str::starts_with
, str::ends_with
,
str::contains
and str::cmp
.
expect
followed by a function call RS-W1030Calls to expect
followed by a function call should be replaced with
unwrap_or_else
to increase laziness. The argument to expect
is evaluated
eagerly and unconditionally. The argument to unwrap_or_else
is evaluated
lazily and only if required, sometimes leading to lower overhead and fewer
allocations.
unwrap_or
followed by a function call RS-W1031Calls to unwrap_or
followed by a function call should be replaced with
unwrap_or_else
or unwrap_or_default
, to increase laziness. The argument to
unwrap_or
is evaluated eagerly and unconditionally. unwrap_or_else
or
unwrap_or_default
are evaluated lazily and only if required, sometimes
leading to lower overhead and fewer allocations.
Arc<RwLock<HashMap<K, V>>>
RS-P1003Arc<RwLock<HashMap<K, V>>>
has performance concerns, the dashmap
crate provides a much better alternative to concurrent hashmaps.
Hence, Arc<RwLock<HashMap<K, V>>>
is better off replaced by Arc<DashMap<K, V>>
from the dashmap
crate.
.bytes().count()
RS-P1001.bytes().count()
is better written as .len()
which is easier to read and more performant.
.bytes().nth(..)
RS-P1002.bytes().nth(..)
is better written as .as_bytes().get(..)
which is more performant.
.trim()
followed by .split_whitespace()
RS-P1005.split_whitespace()
produces an iterator with preceding and trailing
whitespace removed. Thus, s.trim().split_whitespace()
is equivalent to just
s.split_whitespace()
.
collect()
on iterable to Vec
RS-P1006Collecting Iterator
to Vec
has the possible cost of forcing allocation,
hence instead directly using the iterator is more efficient quite often,
if the Vec
is unnecessary.
.replace(..)
method calls RS-P1007Multiple consecutive replace(..)
calls with the same replacement text can result in poor performance. Oftentimes, these replace
calls can be merged.
Certain str
functions, such as .split()
and .find()
work on patterns that
accept both string literals as well as characters. When using such functions,
prefer char
s over single-character string literals as they are more
performant.
Using .iter().nth(_)
is a method of accessing the n
th element of an
iterable. However, some collections such as slices or VecDeque
s allow direct
access to the n
th element through helper methods such as get
and get_mut
(for mutable access). Not only are these methods more consise, they are also
more performant.
Box::new(T::default())
RS-P1008Box::new(T::default())
is overly verbose, involving two function calls instead of one.
It can be better written as Box::<T>::default()
.
retain()
RS-P1009The collections in Rust (Vec
, VecDeque
, HashMap
, HashSet
, etc.)
provide the retain(..)
method to filter elements matching a given predicate
and discard the rest. The drain(..)
method can be used to do the reverse as well.
Consider using this instead of into_iter().filter().collect()
.
enum
variant RS-A1007Large size differences between enum variants can adversely impact performance,
as the size of the enumeration is bounded by the largest variant.
Having one very large variant can penalize the memory layout of the enum
.