Standard Library Types
It is worth reading through the documentation for common standard library
types—such as Vec
, Option
, Result
, and Rc
/Arc
—to find interesting
functions that can sometimes be used to improve performance.
It is also worth knowing about high-performance alternatives to standard
library types, such as Mutex
, RwLock
, Condvar
, and
Once
.
Vec
The best way to create a zero-filled Vec
of length n
is with vec![0; n]
.
This is simple and probably as fast or faster than alternatives, such as
using resize
, extend
, or anything involving unsafe
, because it can use OS
assistance.
Vec::remove
removes an element at a particular index and shifts all
subsequent elements one to the left, which makes it O(n). Vec::swap_remove
replaces an element at a particular index with the final element, which does
not preserve ordering, but is O(1).
Vec::retain
efficiently removes multiple items from a Vec
. There is an
equivalent method for other collection types such as String
, HashSet
, and
HashMap
.
Option
and Result
Option::ok_or
converts an Option
into a Result
, and is passed an err
parameter that is used if the Option
value is None
. err
is computed
eagerly. If its computation is expensive, you should instead use
Option::ok_or_else
, which computes the error value lazily via a closure.
For example, this:
#![allow(unused)] fn main() { fn expensive() {} let o: Option<u32> = None; let r = o.ok_or(expensive()); // always evaluates `expensive()` }
should be changed to this:
#![allow(unused)] fn main() { fn expensive() {} let o: Option<u32> = None; let r = o.ok_or_else(|| expensive()); // evaluates `expensive()` only when needed }
There are similar alternatives for Option::map_or
, Option::unwrap_or
,
Result::or
, Result::map_or
, and Result::unwrap_or
.
Rc
/Arc
Rc::make_mut
/Arc::make_mut
provide clone-on-write semantics. They make
a mutable reference to an Rc
/Arc
. If the refcount is greater than one, they
will clone
the inner value to ensure unique ownership; otherwise, they will
modify the original value. They are not needed often, but they can be extremely
useful on occasion.
Example 1,
Example 2.
Mutex
, RwLock
, Condvar
, and Once
The parking_lot
crate provides alternative implementations of these
synchronization types. The APIs and semantics of the parking_lot
types are
similar but not identical to those of the equivalent types in the standard
library.
The parking_lot
versions used to be reliably smaller, faster, and more
flexible than those in the standard library, but the standard library versions
have greatly improved on some platforms. So you should measure before switching
to parking_lot
.
If you decide to universally use the parking_lot
types it is easy to
accidentally use the standard library equivalents in some places. You can use
Clippy to avoid this problem.