Standard Library Types
It is worth reading through the documentation for common standard library
types—such as Box
, 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
.
Box
The expression Box::default()
has the same effect as
Box::new(T::default())
but can be faster because the compiler can create the
value directly on the heap, rather than constructing it on the stack and then
copying it over.
Example.
Vec
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 that are smaller, faster, and more flexible than those in
the standard library. The APIs and semantics of the parking_lot
types are
similar but not identical to those of the equivalent types in the standard
library.
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.