tutorial: Remove memory model section

This commit is contained in:
Brian Anderson 2013-01-10 15:22:22 -08:00
parent fe0f84823a
commit 22ed202b61

View File

@ -841,76 +841,6 @@ as in this example that unpacks the first value from a tuple and returns it.
fn first((value, _): (int, float)) -> int { value }
~~~
# The Rust memory model
At this junction, let's take a detour to explain the concepts involved
in Rust's memory model. We've seen some of Rust's pointer sigils (`@`,
`~`, and `&`) float by in a few examples, and we aren't going to get
much further without explaining them. Rust has a very particular
approach to memory management that plays a significant role in shaping
the subjective experience of programming in the
language. Understanding the memory landscape will illuminate several
of Rust's unique features as we encounter them.
Rust has three competing goals that inform its view of memory:
* Memory safety: Memory that the Rust language can observe must be
guaranteed to be valid. Under normal circumstances, it must be
impossible for Rust to trigger a segmentation fault or leak memory.
* Performance: High-performance low-level code must be able to use
a number of different allocation strategies. Tracing garbage collection must be
optional and, if it is not desired, memory safety must not be compromised.
Less performance-critical, high-level code should be able to employ a single,
garbage-collection-based, heap allocation strategy.
* Concurrency: Rust code must be free of in-memory data races. (Note that other
types of races are still possible.)
## How performance considerations influence the memory model
Most languages that offer strong memory safety guarantees rely on a
garbage-collected heap to manage all of the objects. This approach is
straightforward both in concept and in implementation, but has
significant costs. Languages that follow this path tend to
aggressively pursue ways to ameliorate allocation costs (think the
Java Virtual Machine). Rust supports this strategy with _managed
boxes_: memory allocated on the heap whose lifetime is managed
by the garbage collector.
By comparison, languages like C++ offer very precise control over
where objects are allocated. In particular, it is common to allocate them
directly on the stack, avoiding expensive heap allocation. In Rust
this is possible as well, and the compiler uses a [clever _pointer
lifetime analysis_][borrow] to ensure that no variable can refer to stack
objects after they are destroyed.
[borrow]: tutorial-borrowed-ptr.html
## How concurrency considerations influence the memory model
Memory safety in a concurrent environment involves avoiding race
conditions between two threads of execution accessing the same
memory. Even high-level languages often require programmers to make
correct use of locking to ensure that a program is free of races.
Rust starts from the position that memory cannot be shared between
tasks. Experience in other languages has proven that isolating each
task's heap from the others is a reliable strategy and one that is
easy for programmers to reason about. Heap isolation has the
additional benefit that garbage collection must only be done
per-heap. Rust never "stops the world" to reclaim memory.
Complete isolation of heaps between tasks would, however, mean that
any data transferred between tasks must be copied. While this is a
fine and useful way to implement communication between tasks, it is
also very inefficient for large data structures. To reduce the amount
of copying, Rust also uses a global _exchange heap_. Objects allocated
in the exchange heap have _ownership semantics_, meaning that there is
only a single variable that refers to them. For this reason, they are
referred to as _owned boxes_. All tasks may allocate objects on the
exchange heap, then transfer ownership of those objects to other
tasks, avoiding expensive copies.
# Boxes and pointers
Many modern languages have a so-called "uniform representation" for