Move Unstable Book sections for #[global_allocator] and System to std::alloc docs
This commit is contained in:
parent
fd6e08a1e6
commit
a24924f683
4 changed files with 85 additions and 148 deletions
|
@ -1,72 +0,0 @@
|
||||||
# `global_allocator`
|
|
||||||
|
|
||||||
The tracking issue for this feature is: [#27389]
|
|
||||||
|
|
||||||
[#27389]: https://github.com/rust-lang/rust/issues/27389
|
|
||||||
|
|
||||||
------------------------
|
|
||||||
|
|
||||||
Rust programs may need to change the allocator that they're running with from
|
|
||||||
time to time. This use case is distinct from an allocator-per-collection (e.g. a
|
|
||||||
`Vec` with a custom allocator) and instead is more related to changing the
|
|
||||||
global default allocator, e.g. what `Vec<T>` uses by default.
|
|
||||||
|
|
||||||
Currently Rust programs don't have a specified global allocator. The compiler
|
|
||||||
may link to a version of [jemalloc] on some platforms, but this is not
|
|
||||||
guaranteed. Libraries, however, like cdylibs and staticlibs are guaranteed
|
|
||||||
to use the "system allocator" which means something like `malloc` on Unixes and
|
|
||||||
`HeapAlloc` on Windows.
|
|
||||||
|
|
||||||
[jemalloc]: https://github.com/jemalloc/jemalloc
|
|
||||||
|
|
||||||
The `#[global_allocator]` attribute, however, allows configuring this choice.
|
|
||||||
You can use this to implement a completely custom global allocator to route all
|
|
||||||
default allocation requests to a custom object. Defined in [RFC 1974] usage
|
|
||||||
looks like:
|
|
||||||
|
|
||||||
[RFC 1974]: https://github.com/rust-lang/rfcs/pull/1974
|
|
||||||
|
|
||||||
```rust
|
|
||||||
#![feature(global_allocator, allocator_api, heap_api)]
|
|
||||||
|
|
||||||
use std::alloc::{GlobalAlloc, System, Layout};
|
|
||||||
use std::ptr::NonNull;
|
|
||||||
|
|
||||||
struct MyAllocator;
|
|
||||||
|
|
||||||
unsafe impl GlobalAlloc for MyAllocator {
|
|
||||||
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
|
||||||
System.alloc(layout)
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
|
|
||||||
System.dealloc(ptr, layout)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[global_allocator]
|
|
||||||
static GLOBAL: MyAllocator = MyAllocator;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
// This `Vec` will allocate memory through `GLOBAL` above
|
|
||||||
let mut v = Vec::new();
|
|
||||||
v.push(1);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
And that's it! The `#[global_allocator]` attribute is applied to a `static`
|
|
||||||
which implements the `Alloc` trait in the `std::alloc` module. Note, though,
|
|
||||||
that the implementation is defined for `&MyAllocator`, not just `MyAllocator`.
|
|
||||||
You may wish, however, to also provide `Alloc for MyAllocator` for other use
|
|
||||||
cases.
|
|
||||||
|
|
||||||
A crate can only have one instance of `#[global_allocator]` and this instance
|
|
||||||
may be loaded through a dependency. For example `#[global_allocator]` above
|
|
||||||
could have been placed in one of the dependencies loaded through `extern crate`.
|
|
||||||
|
|
||||||
Note that `Alloc` itself is an `unsafe` trait, with much documentation on the
|
|
||||||
trait itself about usage and for implementors. Extra care should be taken when
|
|
||||||
implementing a global allocator as well as the allocator may be called from many
|
|
||||||
portions of the standard library, such as the panicking routine. As a result it
|
|
||||||
is highly recommended to not panic during allocation and work in as many
|
|
||||||
situations with as few dependencies as possible as well.
|
|
|
@ -1,76 +0,0 @@
|
||||||
# `alloc_system`
|
|
||||||
|
|
||||||
The tracking issue for this feature is: [#32838]
|
|
||||||
|
|
||||||
[#32838]: https://github.com/rust-lang/rust/issues/32838
|
|
||||||
|
|
||||||
See also [`global_allocator`](language-features/global-allocator.html).
|
|
||||||
|
|
||||||
------------------------
|
|
||||||
|
|
||||||
The compiler currently ships two default allocators: `alloc_system` and
|
|
||||||
`alloc_jemalloc` (some targets don't have jemalloc, however). These allocators
|
|
||||||
are normal Rust crates and contain an implementation of the routines to
|
|
||||||
allocate and deallocate memory. The standard library is not compiled assuming
|
|
||||||
either one, and the compiler will decide which allocator is in use at
|
|
||||||
compile-time depending on the type of output artifact being produced.
|
|
||||||
|
|
||||||
Binaries generated by the compiler will use `alloc_jemalloc` by default (where
|
|
||||||
available). In this situation the compiler "controls the world" in the sense of
|
|
||||||
it has power over the final link. Primarily this means that the allocator
|
|
||||||
decision can be left up the compiler.
|
|
||||||
|
|
||||||
Dynamic and static libraries, however, will use `alloc_system` by default. Here
|
|
||||||
Rust is typically a 'guest' in another application or another world where it
|
|
||||||
cannot authoritatively decide what allocator is in use. As a result it resorts
|
|
||||||
back to the standard APIs (e.g. `malloc` and `free`) for acquiring and releasing
|
|
||||||
memory.
|
|
||||||
|
|
||||||
# Switching Allocators
|
|
||||||
|
|
||||||
Although the compiler's default choices may work most of the time, it's often
|
|
||||||
necessary to tweak certain aspects. Overriding the compiler's decision about
|
|
||||||
which allocator is in use is done through the `#[global_allocator]` attribute:
|
|
||||||
|
|
||||||
```rust,no_run
|
|
||||||
#![feature(alloc_system, global_allocator, allocator_api)]
|
|
||||||
|
|
||||||
extern crate alloc_system;
|
|
||||||
|
|
||||||
use alloc_system::System;
|
|
||||||
|
|
||||||
#[global_allocator]
|
|
||||||
static A: System = System;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let a = Box::new(4); // Allocates from the system allocator.
|
|
||||||
println!("{}", a);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
In this example the binary generated will not link to jemalloc by default but
|
|
||||||
instead use the system allocator. Conversely to generate a dynamic library which
|
|
||||||
uses jemalloc by default one would write:
|
|
||||||
|
|
||||||
(The `alloc_jemalloc` crate cannot be used to control the global allocator,
|
|
||||||
crate.io’s `jemallocator` crate provides equivalent functionality.)
|
|
||||||
|
|
||||||
```toml
|
|
||||||
# Cargo.toml
|
|
||||||
[dependencies]
|
|
||||||
jemallocator = "0.1"
|
|
||||||
```
|
|
||||||
```rust,ignore
|
|
||||||
#![crate_type = "dylib"]
|
|
||||||
|
|
||||||
extern crate jemallocator;
|
|
||||||
|
|
||||||
#[global_allocator]
|
|
||||||
static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;
|
|
||||||
|
|
||||||
pub fn foo() {
|
|
||||||
let a = Box::new(4); // Allocates from jemalloc.
|
|
||||||
println!("{}", a);
|
|
||||||
}
|
|
||||||
# fn main() {}
|
|
||||||
```
|
|
|
@ -44,6 +44,29 @@ use core::alloc::{Alloc, GlobalAlloc, AllocErr, Layout};
|
||||||
use core::ptr::NonNull;
|
use core::ptr::NonNull;
|
||||||
|
|
||||||
/// The default memory allocator provided by the operating system.
|
/// The default memory allocator provided by the operating system.
|
||||||
|
///
|
||||||
|
/// This is based on `malloc` on Unix platforms and `HeapAlloc` on Windows,
|
||||||
|
/// plus related functions.
|
||||||
|
///
|
||||||
|
/// This type can be used in a `static` item
|
||||||
|
/// with the `#[global_allocator]` attribute
|
||||||
|
/// to force the global allocator to be the system’s one.
|
||||||
|
/// (The default is jemalloc for executables, on some platforms.)
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use std::alloc::System;
|
||||||
|
///
|
||||||
|
/// #[global_allocator]
|
||||||
|
/// static A: System = System;
|
||||||
|
///
|
||||||
|
/// fn main() {
|
||||||
|
/// let a = Box::new(4); // Allocates from the system allocator.
|
||||||
|
/// println!("{}", a);
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// It can also be used directly to allocate memory
|
||||||
|
/// independently of the standard library’s global allocator.
|
||||||
#[stable(feature = "alloc_system_type", since = "1.28.0")]
|
#[stable(feature = "alloc_system_type", since = "1.28.0")]
|
||||||
pub struct System;
|
pub struct System;
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,68 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
//! Memory allocation APIs
|
//! Memory allocation APIs
|
||||||
|
//!
|
||||||
|
//! In a given program, the standard library has one “global” memory allocator
|
||||||
|
//! that is used for example by `Box<T>` and `Vec<T>`.
|
||||||
|
//!
|
||||||
|
//! Currently the default global allocator is unspecified.
|
||||||
|
//! The compiler may link to a version of [jemalloc] on some platforms,
|
||||||
|
//! but this is not guaranteed.
|
||||||
|
//! Libraries, however, like `cdylib`s and `staticlib`s are guaranteed
|
||||||
|
//! to use the [`System`] by default.
|
||||||
|
//!
|
||||||
|
//! [jemalloc]: https://github.com/jemalloc/jemalloc
|
||||||
|
//! [`System`]: struct.System.html
|
||||||
|
//!
|
||||||
|
//! # The `#[global_allocator]` attribute
|
||||||
|
//!
|
||||||
|
//! This attribute allows configuring the choice of global allocator.
|
||||||
|
//! You can use this to implement a completely custom global allocator
|
||||||
|
//! to route all default allocation requests to a custom object.
|
||||||
|
//!
|
||||||
|
//! ```rust
|
||||||
|
//! use std::alloc::{GlobalAlloc, System, Layout};
|
||||||
|
//!
|
||||||
|
//! struct MyAllocator;
|
||||||
|
//!
|
||||||
|
//! unsafe impl GlobalAlloc for MyAllocator {
|
||||||
|
//! unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
||||||
|
//! System.alloc(layout)
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
|
||||||
|
//! System.dealloc(ptr, layout)
|
||||||
|
//! }
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! #[global_allocator]
|
||||||
|
//! static GLOBAL: MyAllocator = MyAllocator;
|
||||||
|
//!
|
||||||
|
//! fn main() {
|
||||||
|
//! // This `Vec` will allocate memory through `GLOBAL` above
|
||||||
|
//! let mut v = Vec::new();
|
||||||
|
//! v.push(1);
|
||||||
|
//! }
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! The attribute is used on a `static` item whose type implements the
|
||||||
|
//! [`GlobalAlloc`] trait. This type can be provided by an external library:
|
||||||
|
//!
|
||||||
|
//! [`GlobalAlloc`]: ../../core/alloc/trait.GlobalAlloc.html
|
||||||
|
//!
|
||||||
|
//! ```rust,ignore (demonstrates crates.io usage)
|
||||||
|
//! extern crate jemallocator;
|
||||||
|
//!
|
||||||
|
//! use jemallacator::Jemalloc;
|
||||||
|
//!
|
||||||
|
//! #[global_allocator]
|
||||||
|
//! static GLOBAL: Jemalloc = Jemalloc;
|
||||||
|
//!
|
||||||
|
//! fn main() {}
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! The `#[global_allocator]` can only be used once in a crate
|
||||||
|
//! or its recursive dependencies.
|
||||||
|
|
||||||
#![stable(feature = "alloc_module", since = "1.28.0")]
|
#![stable(feature = "alloc_module", since = "1.28.0")]
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue