Skip to content

Q009. Does Rust ownership have a runtime cost?

Short Answer

Basic ownership checking usually adds no runtime owner tracking because it happens at compile time. That does not make all ownership-related operations free: values may be copied or moved, resources must be dropped, and control flow can require drop flags. Rc, Arc, RefCell, and locks add runtime costs only when those abstractions are selected.

Deep Dive

"Zero-cost" means Rust aims not to add bookkeeping beyond what equivalent correct low-level code needs. A String move may transfer a pointer, length, and capacity, while dropping it eventually calls the allocator. Those operations are real, but there is no extra tracing collector or ordinary owner registry.

Potential costs include:

  • copying inline bytes for a move or Copy operation;
  • allocator and deallocator calls;
  • destructor work and recursive drop glue;
  • conditional branches for drop flags;
  • reference-count updates for Rc<T> and atomic updates for Arc<T>;
  • runtime borrow or synchronization checks in types that explicitly provide them.

Optimization can eliminate many moves, copies, stack slots, and drop-flag branches when their effects are not observable.

Internal Model

Ownership analysis runs in the compiler. Generated code retains only the operations required by program semantics and the selected abstractions.

A moved value may never occupy two physical stack slots: the optimizer can keep it in registers, reuse one slot, pass it directly to a callee, or eliminate it entirely. Performance claims must therefore be verified on optimized code and with measurement.

Example

rust
fn main() {
    let first_number = 42_i32;
    let second_number = first_number; // independent Copy value

    let first_text = String::from("rust");
    let second_text = first_text; // ownership transfer

    println!("{first_number} {second_number} {second_text}");
}

Common Mistakes

  • Interpreting "compile-time ownership" as "the program has no runtime costs."
  • Assuming every source-level move becomes a machine-level copy.
  • Blaming ownership for costs introduced by allocation, reference counting, or synchronization.

Follow-ups

  • When can moving a large value be expensive?
  • Why does Arc<T> require atomic reference counting?
  • How can generated code be inspected and benchmarked correctly?

References

  • Rust Reference
  • rustc-dev-guide
  • The Rust Performance Book