mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-26 14:43:24 +00:00
tutorial: Remove memory model section
This commit is contained in:
parent
fe0f84823a
commit
22ed202b61
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user