@@ -879,6 +879,82 @@ while (x > 10) { x -= 10; }
879
879
assert x == 10;
880
880
~~~~
881
881
882
+ # The Rust Memory Model
883
+
884
+ At this junction let's take a detour to explain the concepts involved
885
+ in Rust's memory model. Rust has a very particular approach to
886
+ memory management that plays a significant role in shaping the "feel"
887
+ of the language. Understanding the memory landscape will illuminate
888
+ several of Rust's unique features as we encounter them.
889
+
890
+ Rust has three competing goals that inform its view of memory:
891
+
892
+ * Memory safety - memory that is managed by and is accessible to
893
+ the Rust language must be guaranteed to be valid. Under normal
894
+ circumstances it is impossible for Rust to trigger a segmentation
895
+ fault or leak memory
896
+ * Performance - high-performance low-level code tends to employ
897
+ a number of allocation strategies. low-performance high-level
898
+ code often uses a single, GC-based, heap allocation strategy
899
+ * Concurrency - Rust maintain memory safety guarantees even
900
+ for code running in parallel
901
+
902
+ ## How performance considerations influence the memory model
903
+
904
+ Many languages that ofter the kinds of memory safety guarentees that
905
+ Rust does have a single allocation strategy: objects live on the heap,
906
+ live for as long as they are needed, and are periodically garbage
907
+ collected. This is very straightforword both conceptually and in
908
+ implementation, but has very significant costs. Such languages tend to
909
+ aggressively pursue ways to ameliorate allocation costs (think the
910
+ Java virtual machine). Rust supports this strategy with _shared
911
+ boxes_, memory allocated on the heap that may be referred to (shared)
912
+ by multiple variables.
913
+
914
+ In comparison, languages like C++ offer a very precise control over
915
+ where objects are allocated. In particular, it is common to put
916
+ them directly on the stack, avoiding expensive heap allocation. In
917
+ Rust this is possible as well, and the compiler will use a clever
918
+ lifetime analysis to ensure that no variable can refer to stack
919
+ objects after they are destroyed.
920
+
921
+ ## How concurrency considerations influence the memory model
922
+
923
+ Memory safety in a concurrent environment tends to mean avoiding race
924
+ conditions between two threads of execution accessing the same
925
+ memory. Even high-level languages frequently avoid solving this
926
+ problem, requiring programmers to correctly employ locking to unsure
927
+ their program is free of races.
928
+
929
+ Rust solves this problem by starting from the position that memory
930
+ simply cannot be shared between tasks. Experience in other languages
931
+ has proven that isolating each tasks' heap from each other is
932
+ a reliable strategy and one that is easy for programmers to reason
933
+ about. Having isolated heaps additionally means that garbage collection
934
+ must only be done per-heap. Rust never 'stops the world' to garbage
935
+ collect memory.
936
+
937
+ If Rust tasks have completely isolated heaps then that seems to imply
938
+ that any data transferred between them must be copied. While this
939
+ is a fine and useful way to implement communication between tasks,
940
+ it is also very inefficient for large data structures.
941
+
942
+ Because of this Rust also introduces a global "exchange heap". Objects
943
+ allocated here have _ownership semantics_, meaning that there is only
944
+ a single variable that refers to them. For this reason they are
945
+ refered to as _unique boxes_. All tasks may allocate objects on this
946
+ heap, then _move_ those allocations to other tasks, avoiding expensive
947
+ copies.
948
+
949
+ ## What to be aware of
950
+
951
+ Rust has three "realms" in which objects can be allocated: the stack,
952
+ the local heap, and the exchange heap. These realms have corresponding
953
+ pointer types: the borrowed pointer (`&T`), the shared pointer (`@T`),
954
+ and the unique pointer (`~T`). These three sigils will appear
955
+ repeatedly as we explore the language. Learning the appropriate role
956
+ of each is key to using Rust effectively.
957
+
882
958
# Functions
883
959
884
960
Like all other static declarations, such as `type`, functions can be
0 commit comments