集册 Rust 编程语言 自定义内存分配器

自定义内存分配器

欢马劈雪     最近更新时间:2020-08-04 05:37:59

81

custom-allocators.md
commit 6ba952020fbc91bad64be1ea0650bfba52e6aab4

分配内存并不总是最简单的事情,同时通常 Rust 默认会负责它,不过经常自定义内存分配会变得必要。编译器和标准库目前允许在编译时切换目前默认使用的全局分配器。设计目前称作RFC 1183不过这里我们会教你如何获取你自己的分配器并运行起来。

默认分配器

编译器目前自带两个默认分配器:alloc_systemalloc_jemalloc(然而一些目标平台并没有 jemalloc)。这些分配器是正常的 Rust crate 并包含分配和释放内存的 routine 的实现。标准库并不假设使用任何一个编译,而且编译器会在编译时根据被产生的输出类型决定使用哪个分配器。

编译器产生的二进制文件默认会使用alloc_jemalloc(如果可用的话)。在这种情况下编译器“控制了一切”,从它超过了最终链接的权利的角度来看。大体上这意味着分配器选择可以被交给编译器。

动态和静态库,然而,默认使用alloc_system。这里 Rust 通常是其他程序的“客人”或者处于并没有权决定应使用的分配器的世界。为此它求助于标准 API(例如,mallocfree)来获取和释放内存。

切换分配器

虽然编译器默认的选择大部分情况工作良好,也经常需要定制特定的方面。覆盖编译器关于使用哪个分配器的选择可以简单的通过链接到期望的分配器实现:

#![feature(alloc_system)]

extern crate alloc_system;

fn main() {
    let a = Box::new(4); // allocates from the system allocator
    println!("{}", a);
}

在这个例子中生成的二进制文件并不会默认链接到 jemalloc 而是使用了系统分配器。同理生成一个默认使用 jemalloc 的动态库可以写成:

#![feature(alloc_jemalloc)]
#![crate_type = "dylib"]

extern crate alloc_jemalloc;

pub fn foo() {
    let a = Box::new(4); // allocates from jemalloc
    println!("{}", a);
}
# fn main() {}

编写一个自定义分配器

有时甚至 jemalloc 与系统分配器之间的选择都是不够的并需要一个新的自定义的分配器。这种情况你要编写你自己实现了分配器 API(例如与alloc_systemalloc_jemallo相同)的 crate。作为一个例子,让我们看看一个简单的和声明化的alloc_system版本:

展开阅读全文