#memory-allocator #allocator #memory #lock-free #heap

nightly no-std ferroc

快速且无锁的内存分配器库

13个版本 ()

1.0.0-pre.32024年5月13日
1.0.0-pre.22024年3月13日
0.3.0 2024年2月28日
0.2.3 2024年2月26日
0.1.5 2024年2月24日

#131 in 内存管理

MIT/Apache

185KB
3.5K SLoC

Ferroc:一个多线程无锁内存分配器

Build Status Cargo Coverage Documentation License

Ferroc(由“ferrum”和“malloc”组合而成)是一个用Rust编写的无锁并发内存分配器,主要灵感来自mimalloc

这个内存分配器旨在与其他主流内存分配器一样快速,同时提供灵活的配置,例如嵌入式/裸机环境集成。

示例

如果您只想使用另一个内存分配器,您可以使用Ferroc作为具有默认功能的全局分配器

use ferroc::Ferroc;

#[global_allocator]
static FERROC: Ferroc = Ferroc;

fn main() {
    // Using the global allocator API.
    let _vec = vec![10; 100];

    // Manually allocate memory.
    let layout = std::alloc::Layout::new::<u8>();
    let ptr = Ferroc.allocate(layout).unwrap();
    unsafe { Ferroc.deallocate(ptr, layout) };

    // Immediately run some delayed clean-up operations.
    Ferroc.collect(/* force */false);
}

如果您想要更多控制分配器,您可以禁用默认功能并启用您需要的功能

ferroc = {version = "*", default-features = false, features = ["base-mmap"]}
#![feature(allocator_api)]

use core::pin::pin;
use ferroc::{
    arena::Arenas,
    heap::{Heap, Context},
    base::Mmap,
};

fn main() {
    let arenas = Arenas::new(Mmap); // `Arenas` are `Send` & `Sync`...
    let cx = pin!(Context::new(&arenas));
    let heap = Heap::new(cx.as_ref()); // ...while `Context`s and `Heap`s are not.

    // Using the allocator API.
    let mut vec = Vec::new_in(&heap);
    vec.extend([1, 2, 3, 4]);
    assert_eq!(vec.iter().sum::<i32>(), 10);

    // Manually allocate memory.
    let layout = std::alloc::Layout::new::<u8>();
    let ptr = heap.allocate(layout).unwrap();
    unsafe { heap.deallocate(ptr.cast(), layout) }.unwrap();

    // Immediately run some delayed clean-up operations.
    heap.collect(/* force */false);
}

Cargo功能

  • 基本功能:泛型ArenasContextHeap
  • "base-static":基本分配器Static
  • "base-mmap":基于操作系统特定虚拟内存管理器的Mmap基本分配器(需要stdlibc);
  • "global":全局分配器实例化宏config!config_mod!(默认情况下内部线程局部静态会泄露);
  • "libc"libc依赖(如果您想要pthread线程局部析构函数,则在config*!选项中需要pthread);
  • "default":由Mmappthread线程局部析构函数提供的默认全局分配器Ferroc(包括所有上述功能);
  • "c":为C/C++目标提供C函数以及根目录下生成的C/C++头文件 "ferroc.h"
  • "c-override":覆盖默认的分配器函数,如 malloc/freeoperator new/delete,这对于在C/C++项目中嵌入Ferroc很有用(更多详情请参阅 本节);
  • "track-valgrind":基于 crabgrind 的Valgrind内存跟踪支持;
  • "finer-grained":向小桶中添加更多对象大小类型,减少碎片化,但也将最小对齐从16降低到8,可能会导致某些需要SIMD的程序因对齐错误而失败。

C/C++用户的构建过程

  1. 下载并安装最新的夜间Rust工具链
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs |\
    sh -- -y --toolchain nightly --profile minimal -c rust-src
  1. 只需使用 cmakemake 即可
mkdir target && cd target # Required to be `target`. Don't change it to `build` or other names.
cmake .. && make
  1. 如果您想安装库
sudo make install

CMake自然支持如 --install-prefix--config 这样的常见选项。

还有一些自定义选项(通过 cmake -D),您可以使用它们

  • FE_TRACK_VALGRIND:请参阅上面的 "track-valgrind"
  • FE_FINER_GRAINED:请参阅上面的 "finer-grained"
  • FE_PGO_GATHER:启用PGO(Profile-Guided Optimization)收集。
  • FE_PGO_USE:使用从预收集的PGO数据中获得的优化进行构建(这需要在步骤1的第二行追加 llvm-tools)。

基准测试

使用 mimalloc-bench 的子集进行基准测试。在我的笔记本电脑上运行,该电脑拥有16GB的RAM和一个Intel i7-10750H CPU @ 2.60GHz。该过程重复10次。

耗时

Time consumed #1 Time consumed #2

内存消耗

Memory consumed #1 Memory consumed #2

注意事项

此crate仅支持当前最新的夜间Rust编译器,并利用了许多不稳定的功能。请谨慎使用。

许可证

根据您的选择,许可如下

依赖项

~0–1MB
~10K SLoC