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

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
}

Example.

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.